Tim, and list
Sending this here for historical accuracy in case anyone stumbles on this
thread. Maybe it should have been obvious, but to me, it certainly wasn't.
In order to get a mail message to show up in 'Sent Mail' using the latest
pywin32 against, at least in my case, Outlook2003 on windowsXP, be sure to do
two things:
1) set mapiTags.PR_SENTMAIL_ENTRYID *on the message itself* - it was
entirely nonobvious to me that this should be necessary and I only realized it
by tracking back to the original C++ code that my Extended MAPI python code had
been based on and reading a 7 year old comment thread. Thank god everything we
put onto the internet exists in perpetuity. ;-)
2) Do NOT set the delete after submit flag. Doing this will do just as
it says, delete the message entirely after submission - which removes it from
the outbox but doesn't put it in sent because it goes to the bit bucket. This
part was just a logical deduction on my part once I realized I still had
PR_DELETE_AFTER_SUBMIT set from previous monkeying.
Of course, doing number one requires the eid of the sent folder so that you can
set it on the message, and although I'm sure you all know this, for new folks
like me that looks like this:
#get the 'sent items' folder - by default. we will have to get the user's
#desired folder as well, if they've changed it...
hr, props = msgstore.GetProps((mapitags.PR_IPM_SENTMAIL_ENTRYID), 0)
(tag, sent_mail_eid) = props[0]
And the final set of message properties (besides recipients, of course) are:
message.SetProps([(mapitags.PR_BODY_HTML_A,Message),
(mapitags.PR_SUBJECT_A,Subject), (mapitags.PR_SENTMAIL_ENTRYID, sent_mail_eid)
])
Thanks for all your help, everyone!
Now to go off and see if Outlook will put that message wherever I want it if I
set the eid of the "sent" folder to the eid of some other destination folder,
or if it will be "too smart" for me and do something silly like compare the
sentmail eid on the message to the PR_IPM_SENTMAIL_ENTRYID from the message
store. But, in theory, the only *point* of even requiring the SENTMAIL_ENTRYID
to be set on the individual message level is precisely so that you can do
exactly that! So hopefully there will be no shenanigans, but, I've learned
never to expect or assume anything as far as Windows is concerned.
-a
________________________________
From: python-win32
[mailto:[email protected]] On Behalf Of
Aubin LaBrosse
Sent: Thursday, June 06, 2013 12:36 PM
To: Tim Roberts; Python-Win32 List
Subject: Re: [python-win32] PySBinaryArray??
Hi Tim,
I was able to test that clearing the read flag and setting delete after submit
didn't result in the email ending up in sent items. When delete after submit
is set it does however at least get removed from the outbox.
I should probably mention I'm running this against outlook 2003 on windows xp
(as high as we've upgraded here at my job...)
I even tried to explicitly call moveMessages on the outbox folder and move it
to sent items folder 'manually' so to speak - no errors from this, but no joy
either.
I've included my code below for anyone who can see issues with it or has
suggestions.
I don't suppose anyone has an outlook 2003 setup they could try to send an
email via and see if it ends up in sent??
"""module to send mail with Extended MAPI using the pywin32 mapi wrappers..."""
# this was based on Jason Hattingh's C++ code at
http://www.codeproject.com/internet/mapadmin.asp
# written by David Fraser <davidf at sjsoft.com> and Stephen Emslie <stephene
at sjsoft.com>
# you can test this by changing the variables at the bottom and running from
the command line
from win32com.mapi import mapi
from win32com.mapi import mapitags
def SendEMAPIMail(Subject="", Message="", SendTo=None, SendCC=None,
SendBCC=None, MAPIProfile=None):
"""Sends an email to the recipient using the extended MAPI interface
Subject and Message are strings
Send{To,CC,BCC} are comma-separated address lists
MAPIProfile is the name of the MAPI profile"""
# initialize and log on
mapi.MAPIInitialize(None)
session = mapi.MAPILogonEx(0, None, None, mapi.MAPI_EXTENDED |
mapi.MAPI_USE_DEFAULT)
messagestorestable = session.GetMsgStoresTable(0)
messagestorestable.SetColumns((mapitags.PR_ENTRYID,
mapitags.PR_DISPLAY_NAME_A, mapitags.PR_DEFAULT_STORE),0)
foundDefStore = False
while (True):
foundDefStore = False
rows = messagestorestable.QueryRows(1, 0)
if len(rows) != 1:
break
row = rows[0]
for x in range(len(row)):
propertyid, propertyvalue = row[x]
if (propertyid == mapitags.PR_DEFAULT_STORE and propertyvalue ==
True):
foundDefStore = True
break
if (foundDefStore):
break
# unpack the row and open the message store
(eid_tag, eid), (name_tag, name), (def_store_tag, def_store) = row
msgstore = session.OpenMsgStore(0,eid,None,mapi.MDB_NO_DIALOG |
mapi.MAPI_BEST_ACCESS)
# get the outbox
hr, props = msgstore.GetProps((mapitags.PR_IPM_OUTBOX_ENTRYID), 0)
(tag, eid) = props[0]
outboxfolder = msgstore.OpenEntry(eid,None,mapi.MAPI_BEST_ACCESS)
#get the 'sent items' folder - by default. we will have to get the user's
#desired folder as well, if they've changed it...
hr, props = msgstore.GetProps((mapitags.PR_IPM_SENTMAIL_ENTRYID), 0)
(tag, eid) = props[0]
destFolder = msgstore.OpenEntry(eid, None, mapi.MAPI_BEST_ACCESS)
# create the message and the addrlist
message = outboxfolder.CreateMessage(None,0)
# note: you can use the resolveaddress functions for this. but you may get
headaches
pal = []
def makeentry(recipient, recipienttype):
return ((mapitags.PR_RECIPIENT_TYPE, recipienttype),
(mapitags.PR_SEND_RICH_INFO, False),
(mapitags.PR_DISPLAY_TYPE, 0),
(mapitags.PR_OBJECT_TYPE, 6),
(mapitags.PR_EMAIL_ADDRESS_A, recipient),
(mapitags.PR_ADDRTYPE_A, 'SMTP'),
(mapitags.PR_DISPLAY_NAME_A, recipient))
if SendTo:
pal.extend([makeentry(recipient, mapi.MAPI_TO) for recipient in
SendTo.split(",")])
if SendCC:
pal.extend([makeentry(recipient, mapi.MAPI_CC) for recipient in
SendCC.split(",")])
if SendBCC:
pal.extend([makeentry(recipient, mapi.MAPI_BCC) for recipient in
SendBCC.split(",")])
# add the resolved recipients to the message
message.ModifyRecipients(mapi.MODRECIP_ADD,pal)
message.SetProps([(mapitags.PR_BODY_HTML_A,Message),
(mapitags.PR_SUBJECT_A,Subject), (mapitags.PR_DELETE_AFTER_SUBMIT, 1)])
# save changes and submit
outboxfolder.SaveChanges(0)
message.SubmitMessage(0)
message.SetReadFlag(0)
#get the message id so i can move it...
hr, props = message.GetProps((mapitags.PR_ENTRYID),0)
(msg_eid_tag, msg_eid) = props[0]
#1 is MESSAGE_MOVE according to msdn docs but i don't feel like figuring out if
it has a symbolic constant or not...
outboxfolder.CopyMessages([msg_eid], None, destFolder, 0, None, 1)
________________________________
From: Tim Roberts [mailto:[email protected]]
Sent: Wednesday, June 05, 2013 10:35 AM
To: Aubin LaBrosse; Python-Win32 List
Subject: Re: [python-win32] PySBinaryArray??
Aubin LaBrosse wrote:
Mail server is exchange
Last calls I made are:
outboxfolder.SaveChanges(0)
message.SubmitMessage(0)
outlook is 100% online, yes
for whatever reason when I send programmatically in this way I never see it
move to sent items - it just hangs out in the outbox. So I just assumed I had
to move it myself.
No, that's not the right answer. You don't really want the message in "Sent
Items". What you want is for Outlook to move it to "Sent Items" because it got
sent. Did you say you had tried doing this before SaveChanges:
message.SetReadFlag(CLEAR_READ_FLAG)
message.SetProps([(mapitags.PR_DELETE_AFTER_SUBMIT,1)])
--
Tim Roberts, [email protected]<mailto:[email protected]>
Providenza & Boekelheide, Inc.
_______________________________________________
python-win32 mailing list
[email protected]
http://mail.python.org/mailman/listinfo/python-win32