- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am getting daily automatically generated e-mails from our local weather bureau. The e-mail contains a .zip attachment. I have been trying to find a way to automatically open the e-mail and place the attachment in a standard folder where I can arrange for a Fortran program to deal with it as a scheduled task.
I have downloaded Jugoslav's excellent MAPItest program (from his home page) and tried to modify it to receive e-mails as well as send them, but with no success.
Does anyone have any experience with this sort of thing? I would value any suggestions related to any method of doing this.
With many thanks,
Mike
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
1) Call MAPIReadMail to extract the whole message to a temporary file (now, I'm not sure how you get the lpszMessageID)
2) You get an array lppMessage of MapiMessage structures, each containing nFileCount and lpFiles, pointing to an array of MapiFileDesc structure
3) Each MapiFileDesc contains information about the extracted attachment.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for your input. I am using Outlook 2007. I have already spent many hours searching the Web and have found a wealth of stuff out there, but since I can already use Jugoslav's Fortran to send e-mails I would like to pursue it a little furthre before I try something else.
From my reading of the documentation I believe I need to logon ...
iret = MAPILogon(0, "Microsoft Outlook"C, ""C, 0, 0, LOC(hSession)) !Works OK
Then I must call MAPIFindNext ...
iret = MAPIFindNext(hSession,0,""C,""C,MAPI_UNREAD_ONLY,0,msgID) !Seems to work, but see below
After which I must call MAPIReadMail ...
iret = MAPIReadMail(hSession, 0, msgID, MAPI_BODY_AS_FILE, 0,msg ) !This fails.
I think the problem lies with the call to MAPIFindNext which returns a message ID (msgID). The actual value I get for msgID is always something like BC@>l9&![eR, in other words, what looks like the character representation of a series of random bytes - I would expect to see something I can at least partially read. I have tried dozens of variations of the above but without success.
Many thanks for any further insights.
Mike
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think the problem lies with the call to MAPIFindNext which returns a message ID (msgID). The actual value I get for msgID is always something like BC@>l9&![eR, in other words, what looks like the character representation of a series of random bytes - I would expect to see something I can at least partially read. I have tried dozens of variations of the above but without success.
Many thanks for any further insights.
Mike
As I get it, the msgID is an opaque string, i.e. a message handle of sorts, so you cannot deduce anything from its contents.
For each retrieved message, you should call MAPIReadMail with ulUIParam=MAPI_ENVELOPE_ONLY, which would extract only the message header into the MapiMessage structure. If the contents match your filter, only then call MAPIReadMail for that message with full contents & attachments. You will probably want to .OR. the MAPI_PEEK flag, in order to not mark all examined messages as read.
By the way, I've stumbled upon this piece of info on that same page that you may find useful:
File attachments are saved to temporary files, and the names are returned to the caller in the message structure...
The caller is responsible for freeing the MapiMessage structure by calling the MAPIFreeBuffer function and deleting any files associated with attachments included with the message.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
MAPIFindNext does seem to be working OK - I get a different msgID depending on which flag I use, and with MAPI_UNREAD_ONLY, if there are no unread messages, MAPIFindNext tells me so. But MAPIReadMail is a no-go for me, and yetI am sure, from all the reading I have done, I am using it correctly.
Thanks for your help
Mike
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Check out MAPI.F90. You will find the following:
lpMAPIReadMail = GetProcAddress(hMapiLib,"MAPISaveMail"C)
bOK = bOK.and.(lpMAPIReadMail.ne.0)
lpMAPISaveMail = GetProcAddress(hMapiLib,"MAPIReadMail"C)
bOK = bOK.and.(lpMAPISaveMail.ne.0)
Note that you will now try MAPISaveMail when you think you are trying MAPIReadMail, and vice versa!
When I found this, I corrected the code and the MAPIReadMail FINALLY worked with return code zero.
I used
iret = MAPIReadMail(hSession, 0, MsgID, MAPI_BODY_AS_FILE, 0,newmsg )
but the only item set in the returned message structure newmsg is the first ULRESERVED component. This points to an address in memory where, after a few garbage characters, some real e-mail stuff can be seen, e.g. subject, sender etc. So there is hope!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
After the MAPIReadmail puts a pointer into the UlReserved component, a look at that address yields the attached memory picture.
The Address pointed to is 3E60890.
The first 48 bytes appear to be rubbish, however, if you look at bytes 5 to 8, note that they are C0 08 E6 03.
If you write them in reverse, you get an address 03 E6 08 C0 which is nearby and, lo and behold, if you look at the contents you find that it is the starting point of the message subject text.
Similarly, bytes 17 -20, taken in reverse order, yield 03 E6 08 C0, which is a nearby address that yields the message received date.
Further examination of the memory block yields the path to a temporary file containing the message body, and so on.
So what needs to be discovered is why the extracted data about the message is not being distributed correctly into the MAPIMESSAGE structure, even though the mail message data is being found OK.
(P.S. this was done using CVF and MS DEvStudio. The MAPI32.DLL I have is dated 2004)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Check out MAPI.F90. You will find the following:
lpMAPIReadMail = GetProcAddress(hMapiLib,"MAPISaveMail"C)
bOK = bOK.and.(lpMAPIReadMail.ne.0)
lpMAPISaveMail = GetProcAddress(hMapiLib,"MAPIReadMail"C)
bOK = bOK.and.(lpMAPISaveMail.ne.0)
Damn, and after Mike's post I even double-checked the INTERFACEs in MAPI.f90, but checking this part seemed really over the top. Thanks for spotting that. I suppose I'll have to update the website after some time...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- lppMessage [out]
-
Pointer to the location where the message is written.
[fortran]!DEC$ATTRIBUTES REFERENCE:: lppMessage type(t_MapiMessage) lppMessagewith
[/fortran]
[fortran]type(t_MapiMessage), pointer:: lppMessage(AFAIK, the REFERENCE is not necessary when the argument is pointer?). Since it must be released with MAPIFreeBuffer, I guess that MAPI does the memory (de)allocation, ergo we need a pointer here (a Fortran pointer will do, although integer(LPVOID) is much cleaner interface -- you just need to dereference it with a pointer(lpMessage, newmessage))
[/fortran]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You have hit the nail on the head.
The following works:
In MAPI.F90 put
interface
integer function MAPIReadMail(lhSession,ulUIParam,lpszMessageID,flFlags,ulReserved,lppMessage)
!DEC$ATTRIBUTES STDCALL:: MAPIReadMail
use mapity
integer lhSession
integer ulUIParam
!DEC$ATTRIBUTES REFERENCE:: lpszMessageID
character(*) lpszMessageID
integer flFlags
integer ulReserved
!DEC$ATTRIBUTES REFERENCE:: lppMessage
Integer lppmessage
end function
end interface
pointer(lpMAPIReadMail,MAPIReadMail)
In MAPITEST.F90 put
type(t_MapiMessage) :: NewMsg
pointer(lppmessage,NewMsg)
.....
.....
iret = MAPIReadMail(hSession, 0, MsgID, MAPI_BODY_AS_FILE, 0,lppmessage )
and sure enough, when lppmessage is dereferenced, NEWMSG is correctly populated with all the message details!
Well done.
P.S. How to deal with the Originator, Recipients and Files descriptors?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Since you opened the new thread, I replied there.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have been away for a few days so missed all the interesting discussion between yourselves on this thread and the other one (Dereferencing a C++ array ...). I just want to say thank you for some great input - all my problems are basically solved now. The only potential show stopper in my plan is Outlook's insistence on warning me that a program is trying to read my e-mail - although the trust centre gives an option to allow a program to send e-mail, receiving e-mail doesn't get a mention. If anyone has any ideas ... ?
But thanks again - I learnt heaps.
Mike
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page