Saving the item should be enough.
If you can see the property in OutlookSpy then it's there in the recipient
entry in the recipients table.
Maybe it's the code used. You haven't shown a code sample, let's see that
and see if anyone spots anything.

Signature
Ken Slovak
[MVP - Outlook]
http://www.slovaktech.com
Author: Absolute Beginner's Guide to Microsoft Office Outlook 2003
Reminder Manager, Extended Reminders, Attachment Options
http://www.slovaktech.com/products.htm
>I do MailItem.Save in the code, but it dosn't seem to help.
>
[quoted text clipped - 7 lines]
>
> I have Exchange profile
Just to remind the problem
If I create a new email and start typing email address in To, Outlook
suggests some emails in a popup
Most emails look like Slava Barouline < email@com > , but sme have only
address or display name
The later fill recipients table incorrectly and don't get resolved even if I
call MailItem.Save in my code
I suspect Outlook delays resolving for some reason.
If I save email in Outlook by pressing a button, emails get resolved and
look OK in recipients table
Here it is (very scary code):
//Save before processing sent email:
.....
//Save before accessing PR_BODY
FMailItemToProcess.Save;
ASubject := FMailItemToProcess.Subject;
ABody := GetEmailBody;
...
//Get Recipients List
AnEmailAddresses := GetRecipientEmailAddresses;
.....
//Get emails from recipients table
function TMessageProcessor.GetRecipientEmailAddresses: TStringList;
var
OneMessage: IMessage;
RecTable:IMAPITable;
begin
RecTable:=nil;
OneMessage :=IUnknown(FMailItemToProcess.MAPIOBJECT) as IMessage;
OleCheck(OneMessage.GetRecipientTable(0,RecTable));
result := GetRecipientEmailAddressesFromTable(RecTable);
RecTable := nil;
OneMessage := nil;
end;
function
TMessageProcessor.GetRecipientEmailAddressesFromTable(RecTable:IMAPITable):
TStringList;
type
LTSPropTagArray =
record
cValues : ULONG;
aulPropTag : array[0..3] of ULONG;
end;
const
FPropTagArray : LTSPropTagArray = (cValues:4;
aulPropTag:(
PR_DISPLAY_NAME,
PR_EMAIL_ADDRESS,
PR_ADDRTYPE,
PR_ENTRYID)
);
var
NRec :integer;
ListRecTable:IMAPITable;
RecCount:Ulong;
lppRows:PSRowSet;
EMailAddress, AnAddressType, ADisplayName: string;
i: Integer;
DistList: IDistList;
AddrBook: IAddrBook;
lpcbeid, ulObjectType: ULONG;
lppeid: PENTRYID;
ProcessInternalEmails, AskConfirmation: Boolean;
begin
result := TStringList.Create;
lppRows:=nil;
ProcessInternalEmails := False;
AskConfirmation := True;
OleCheck(RecTable.SetColumns(@FPropTagArray,TBL_BATCH));
OleCheck(RecTable.GetRowCount(0,RecCount));
dmMain.LogLine('Found ' + IntToStr(RecCount) + ' recipient(s)');
if RecCount>0 then
try
OleCheck(RecTable.QueryRows(RecCount,TBL_NOADVANCE,lppRows));
for Nrec:=0 to RecCount-1 do
begin
// PR_EMAIL_ADDRESS is an optional property
// therefore we must access it in a try except
try
AnAddressType :=
lppRows.aRow[Nrec].lpProps[lppRows.aRow[Nrec].cValues-2].Value.lpsza;
if UpperCase(AnAddressType) = 'MAPIPDL' then
begin
dmMain.LogLine('Found private distribution list - trying to
expand');
//!!! Get DistList
AddrBook := GetAddressBook;
//The IAddrBook.OpenEntry method opens an address book entry
//and returns a pointer to an interface that can be used
//to access the entry.
lpcbeid :=
lppRows.aRow[Nrec].lpProps[lppRows.aRow[Nrec].cValues-1].Value.bin.cb;
lppeid :=
LPENTRYID(lppRows.aRow[Nrec].lpProps[lppRows.aRow[Nrec].cValues-1].Value.bin.lpb);
DistList:=nil;
ulObjectType:=8; //MAPI_DISTLIST
OleCheck(AddrBook.OpenEntry(
lpcbeid,
lppeid,
@IID_IDistList,
MAPI_BEST_ACCESS or MAPI_DEFERRED_ERRORS,
ulObjectType,
IUnknown(DistList)));
OleCheck(DistList.GetContentsTable(0,ListRecTable));
with GetRecipientEmailAddressesFromTable(ListRecTable) do
for i:= 0 to Count - 1 do
result.AddObject(Strings[i], Objects[i]);
DistList:=nil;
ListRecTable := nil;
end
//Check Exchange email address type and ProcessInternalEmails
setting
else if (UpperCase(AnAddressType) = 'EX')
and not dmMain.ProcessInternalEmails then
begin
if ProcessInternalEmails then
begin
EMailAddress :=
lppRows.aRow[Nrec].lpProps[lppRows.aRow[Nrec].cValues-3].Value.lpsza;
ADisplayName :=
lppRows.aRow[Nrec].lpProps[lppRows.aRow[Nrec].cValues-4].Value.lpsza;
dmMain.LogLine('Recipient #' + IntToStr(Nrec + 1) + ' - email
address: ' + EMailAddress + ' , display name: ' + ADisplayName);
result.AddObject(EMailAddress,
TStringObject.Create(ADisplayName));
end
else
begin
EMailAddress :=
lppRows.aRow[Nrec].lpProps[lppRows.aRow[Nrec].cValues-3].Value.lpsza;
ADisplayName :=
lppRows.aRow[Nrec].lpProps[lppRows.aRow[Nrec].cValues-4].Value.lpsza;
dmMain.LogLine('Recipient #' + IntToStr(Nrec + 1) + ' - email
address: ' + EMailAddress + ' , display name: ' + ADisplayName);
dmMain.LogLine('Email address has Exchange address type');
//Manual processing
if AskConfirmation and FIsManualProcessing then
begin
if MessageDlg(strExchangeRecipientAddressTypeConfirmation,
mtConfirmation, [mbYes, mbNo], 0) = mrYes then
begin
ProcessInternalEmails := True;
result.AddObject(EMailAddress,
TStringObject.Create(ADisplayName));
end
else
begin
ProcessInternalEmails := False;
dmMain.LogLine('Email address skipped');
end;
AskConfirmation := False;
end
//Automatic processing - skip
else
dmMain.LogLine('Email address skipped');
end;
end
else
begin
//In case PR_EMAIL_ADDRESS is not found, use PR_DISPLAY_NAME
instead
ADisplayName :=
lppRows.aRow[Nrec].lpProps[lppRows.aRow[Nrec].cValues-4].Value.lpsza;
try
EMailAddress :=
lppRows.aRow[Nrec].lpProps[lppRows.aRow[Nrec].cValues-3].Value.lpsza;
except
dmMain.LogLine('Failed to read PR_EMAIL_ADDRESS, using
PR_DISPLAY_NAME instead');
EMailAddress := ADisplayName;
end;
dmMain.LogLine('Recipient #' + IntToStr(Nrec + 1) + ' - email
address: ' + EMailAddress + ' , display name: ' + ADisplayName);
result.AddObject(EMailAddress,
TStringObject.Create(ADisplayName));
end;
except
on e: Exception do
dmMain.LogLine('Failed to read email address from recipient table
row with error message: ' + e.Message);
end;
end;
except
on e: Exception do
dmMain.LogLine('Failed to retrieve recipients table with error
message: ' + e.Message);
end;
// Free each element in the pRows buffer
FreeProws(lppRows);
end;
> Saving the item should be enough.
>
[quoted text clipped - 3 lines]
> Maybe it's the code used. You haven't shown a code sample, let's see that
> and see if anyone spots anything.
Ken Slovak - [MVP - Outlook] - 29 Aug 2006 14:53 GMT
I don't see anything offhand but I'm no C++ programmer or even Extended MAPI
programmer.
Have you tried resolving the recipients collection (Recipients.ResolveAll)
and seeing if that helps?
One thing is if the email addresses are in the GAL and the email display
name is not unique in the GAL then resolution will fail. In that case the
alias must be fully qualified to resolve ("joe@foobar.com") and not just
"joe".

Signature
Ken Slovak
[MVP - Outlook]
http://www.slovaktech.com
Author: Absolute Beginner's Guide to Microsoft Office Outlook 2003
Reminder Manager, Extended Reminders, Attachment Options
http://www.slovaktech.com/products.htm
> Just to remind the problem
> If I create a new email and start typing email address in To, Outlook
[quoted text clipped - 223 lines]
>
> end;