Some of our applications which work fine with different ways of email integration, using mailto:
, simulated "Send To...", and SMTP in Windows 2000 and 2003 environments, now move to a new Windows 2008 system with Exchange 2010 and Outlook 2010 clients.
We have one use case where the application creates a new mail, sets recipient(s) and subject, adds one or more attachments and then opens it in the default mail client so it can be edited by the user before sending.
Do you know a solution which works in the new environment? Should we use a third party library? Or is there some OLE automation code available which is known to work, using Outlook.Applicati开发者_开发技巧on?
We use JclSimpleBringUpSendMailDialog from the jclMapi unit in the Jedi JCL library.
I once had an app where we built in a user option to specify whether they wanted to use SMTP or MAPI and then all sorts of mail server settings but the Jedi library call makes life so much easier. If end users have gone to the trouble of setting up all their settings in a MAPI client then why would they want to set them all up again in my/our software.
The trouble with the mailto:// stuff is that it's often not quite configurable enough or the mail client doesn't handle the parameters in the same/standard way - then users think your software's rubbish rather than believe they have a dodgy mail client.
So we just use the MAPI interface. Easy.
I use this unit - it credits Brian Long ages ago...
unit UArtMAPI;
interface
procedure ArtMAPISendMail(
const Subject, MessageText, MailFromName, MailFromAddress,
MailToName, MailToAddress: String;
const AttachmentFileNames: array of String);
implementation
uses
SysUtils,
Windows,
UArtLibrary,
Dialogs,
Forms,
MAPI;
procedure ArtMAPISendMail(
const Subject, MessageText, MailFromName, MailFromAddress,
MailToName, MailToAddress: String;
const AttachmentFileNames: array of String);
//Originally by Brian Long: The Delphi Magazine issue 60 - Delphi And Email
var
MAPIError: DWord;
MapiMessage: TMapiMessage;
Originator, Recipient: TMapiRecipDesc;
Files, FilesTmp: PMapiFileDesc;
FilesCount: Integer;
begin
FillChar(MapiMessage, Sizeof(TMapiMessage), 0);
MapiMessage.lpszSubject := PAnsiChar(AnsiString(Subject));
MapiMessage.lpszNoteText := PAnsiChar(AnsiString(MessageText));
FillChar(Originator, Sizeof(TMapiRecipDesc), 0);
Originator.lpszName := PAnsiChar(AnsiString(MailFromName));
Originator.lpszAddress := PAnsiChar(AnsiString(MailFromAddress));
// MapiMessage.lpOriginator := @Originator;
MapiMessage.lpOriginator := nil;
MapiMessage.nRecipCount := 1;
FillChar(Recipient, Sizeof(TMapiRecipDesc), 0);
Recipient.ulRecipClass := MAPI_TO;
Recipient.lpszName := PAnsiChar(AnsiString(MailToName));
Recipient.lpszAddress := PAnsiChar(AnsiString(MailToAddress));
MapiMessage.lpRecips := @Recipient;
MapiMessage.nFileCount := High(AttachmentFileNames) - Low(AttachmentFileNames) + 1;
Files := AllocMem(SizeOf(TMapiFileDesc) * MapiMessage.nFileCount);
MapiMessage.lpFiles := Files;
FilesTmp := Files;
for FilesCount := Low(AttachmentFileNames) to High(AttachmentFileNames) do
begin
FilesTmp.nPosition := $FFFFFFFF;
FilesTmp.lpszPathName := PAnsiChar(AnsiString(AttachmentFileNames[FilesCount]));
Inc(FilesTmp)
end;
try
MAPIError := MapiSendMail(
0,
Application.MainForm.Handle,
MapiMessage,
MAPI_LOGON_UI {or MAPI_NEW_SESSION},
0);
finally
FreeMem(Files)
end;
case MAPIError of
MAPI_E_AMBIGUOUS_RECIPIENT:
Showmessage('A recipient matched more than one of the recipient descriptor structures and MAPI_DIALOG was not set. No message was sent.');
MAPI_E_ATTACHMENT_NOT_FOUND:
Showmessage('The specified attachment was not found; no message was sent.');
MAPI_E_ATTACHMENT_OPEN_FAILURE:
Showmessage('The specified attachment could not be opened; no message was sent.');
MAPI_E_BAD_RECIPTYPE:
Showmessage('The type of a recipient was not MAPI_TO, MAPI_CC, or MAPI_BCC. No message was sent.');
MAPI_E_FAILURE:
Showmessage('One or more unspecified errors occurred; no message was sent.');
MAPI_E_INSUFFICIENT_MEMORY:
Showmessage('There was insufficient memory to proceed. No message was sent.');
MAPI_E_LOGIN_FAILURE:
Showmessage('There was no default logon, and the user failed to log on successfully when the logon dialog box was displayed. No message was sent.');
MAPI_E_TEXT_TOO_LARGE:
Showmessage('The text in the message was too large to sent; the message was not sent.');
MAPI_E_TOO_MANY_FILES:
Showmessage('There were too many file attachments; no message was sent.');
MAPI_E_TOO_MANY_RECIPIENTS:
Showmessage('There were too many recipients; no message was sent.');
MAPI_E_UNKNOWN_RECIPIENT:
Showmessage('A recipient did not appear in the address list; no message was sent.');
MAPI_E_USER_ABORT:
Showmessage('The user canceled the process; no message was sent.');
SUCCESS_SUCCESS:
Showmessage('MAPISendMail successfully sent the message.');
else
Showmessage('MAPISendMail failed with an unknown error code.');
end;
end;
end.
Maybe this can be useful for you. But I can't test it, because I'm thunderbird user.
I dug up this example. It's from 2002, so uses an older outlook version, but the idea should still be the same. It was used in an application to send newly registered users their userid and password (don't start me on that, it was just a way to restrict access to a site, nothing sensitive there). The messages are saved in the Outbox, not opened, but if you dig through the OleServer and Outlook8 (number will be higher by now), you should find ways to open the mail for user attention instead of saving it straight to the outbox.
The entire Outlook object model can be found on msdn: http://msdn.microsoft.com/en-us/library/aa221870%28v=office.11%29.aspx
Another good source for information about Office Automation are Deborah Pate's pages: http://www.djpate.freeserve.co.uk/Automation.htm
function TStapWerkt_data.GenerateMailsOutlook(SendDBF: boolean): boolean;
var
Outlook: TOutlookApplication;
olNameSpace: NameSpace;
MailIt: TMailItem;
AttachedFile: OleVariant;
i: integer;
emailaddress: string;
begin
Result := true;
Outlook := TOutlookApplication.Create( nil );
try
Outlook.ConnectKind := ckNewInstance;
try
Outlook.Connect;
try
olNameSpace := Outlook.GetNamespace('MAPI');
olNameSpace.Logon('', '', False, False);
try
if SendDBF then begin
MailIt := TMailItem.Create( nil );
MailIt.ConnectTo( Outlook.CreateItem( olMailItem ) as MailItem );
try
MailIt.Recipients.Add( 'info@bjmsoftware.com' );
MailIt.Subject := 'StapWerk.dbf';
MailIt.Body := 'Stap'#13#10;
AttachedFile := IncludeTrailingBackslash( ExtractFilePath(
Stap_db.Stap_Database.DatabaseName ) ) + 'stapwerk.dbf';
MailIt.Attachments.Add( AttachedFile, EmptyParam, EmptyParam, EmptyParam );
MailIt.Save;
finally
MailIt.Free;
end;
end;
for i := 0 to FNewUsers.Count - 1 do begin
MailIt := TMailItem.Create( nil );
MailIt.ConnectTo( Outlook.CreateItem( olMailItem ) as MailItem );
try
emailaddress := TStapper( FNewUsers.Items[i] ).Email;
if emailaddress = '' then begin
emailaddress := C_MailUnknownAddress;
end;
MailIt.Recipients.Add( emailaddress );
MailIt.Subject := C_MailSubject;
MailIt.Body := Format( C_MailBody,
[TStapper( FNewUsers.Items[i] ).UserId,
TStapper( FNewUsers.Items[i] ).Password] );
MailIt.Save;
finally
MailIt.Free;
end;
end;
finally
olNameSpace.Logoff;
end;
finally
Outlook.Disconnect;
// We kunnen ondanks ckNewInstance quit niet gebruiken
// Outlook lijkt de connectkind te negeren en hoe dan ook te koppelen
// naar een bestaande instantie. En die gooi je dan dus ook dicht met quit.
// Outlook.quit;
end;
finally
Outlook.free;
end;
except
on E: Exception do begin
Result := false;
end;
end;
end;
Maybe this is the easiest way to open an email window
System("mailto:someone@example.com?Subject=Hello%20again&body=your%20textBody%20here")
精彩评论