给定一些文件(或shell文件对象)如何用它们调用.MAPIMail
已注册的shell扩展处理程序?
我在电脑上有一些文件:
C:\Users\ian\AppData\Local\Temp\Contoso_Invoice_141174.pdf
C:\Users\ian\AppData\Local\Temp\Contoso_Invoice_141173.pdf
C:\Users\ian\AppData\Local\Temp\Contoso_Invoice_141171.pdf
我想将编程等同于将它们放在.MAPIMail
已注册的处理程序上:
发送至文件夹的邮件收件人选项实际上是一个特殊注册的.MAPIMail
扩展程序:
这是在系统上注册的文件类型:
HKEY_CLASSES_ROOT\.mapimail
如何调用drop到一个短暂的.mapimail
文件?
现在,我可能是一个糟糕的开发人员,并在注册表中填写.mapimail
条目的默认值:
CLSID\{9E56BE60-C50F-11CF-9A2C-00A0C90A90CE}
提取clsid {9E56BE60-C50F-11CF-9A2C-00A0C90A90CE}
,并确认该类已注册:
HKEY_CLASSES_ROOT\CLSID\{9E56BE60-C50F-11CF-9A2C-00A0C90A90CE}
(default) = Desktop Shortcut
\InProcServer32
(default) = %SystemRoot%\System32\sendmail.dll
使用CoCreateInstance
创建该COM对象:
IUnknown unk = CreateComObject("{9E56BE60-C50F-11CF-9A2C-00A0C90A90CE}");
然后我处于一个无证件,不受支持的世界,在那里我不知道我有QueryInterface
的接口,以及以什么顺序调用的方法。
我想要的是可能涉及shell的内容(伪代码):
IShellFolder desktop;
OleCheck(SHGetDesktopFolder(out desktop));
List<pidl> pidls = new List<pidl>();
ULONG chEaten = 0;
ULONG dwAttributes = 0;
PIDL pidl;
foreach (String filename in Files) do
{
OleCheck(desktop.ParseDisplayName(0, nil, filename, out chEaten, out pidl, ref dwAttributes));
pidls.Add(pidl);
}
//Get the shell folder of the temp folder
IShellFolder tempShellFolder;
desktop.ParseDisplayName(0, nil, GetTemporaryPath, out chEaten, out pidl, ref dwAttributes));
desktop.BindToObject(pidl, nil, IShellFolder, tempShellFolder);
//i have no idea what i've been doing; just throwing reasonable looking code together
//nobody will actually ever read this
IDontCare context;
tempShellFolder.GetUIObjectOf(0, pidls.Count, pidls, IDontCareAnymore, nil, ref context);
除了所有代码依赖于上下文菜单的延伸,我没有。没有人说.MAPIMail
必须在任何情况下发送到菜单。
我问的是如何删除.mapimail
文件上的文件。
我的上帝。
因为在安装了Office 64位的Windows 64位上运行的32位应用程序中没有安装MAPI客户端。所以我需要能够完成用户已经可以做到的事情。
答案 0 :(得分:3)
虽然它没有回答我的问题,雷蒙德指出这是一个愚蠢的问题。在他们正确的思想中,没有人应该尝试向收件人发送邮件。但我绝望了!
原来我并没有被完全卡住。虽然从32位应用程序(或反之亦然)处理64位Outlook(MAPI提供程序)时存在 bitness 噩梦,但还有一个。
如果我使用只 MapiSendMail
和没有其他 MAPI功能,则可以安全地跨越32位/ 64位屏障。来自Building MAPI Applications on 32-Bit and 64-Bit Platforms:
32位MAPI应用程序和64位Outlook
不支持在安装了64位Outlook和64位Windows的计算机上运行32位MAPI应用程序。应用程序开发人员必须将应用程序更新并重建为64位平台的64位应用程序。这是因为32位应用程序无法加载64位Msmapi32.dll文件。应用程序开发人员必须包含少量API更改,才能在64位环境中成功构建代码。已使用这些更改更新MAPI头文件以支持64位平台。您可以在Outlook 2010: MAPI Header Files下载这些头文件。开发人员可以使用同一组MAPI头文件来构建32位和64位MAPI应用程序
这听起来好像都失去了希望。但是,在Windows 7上有:
异常:MAPISendMail
但是,所有简单MAPI和MAPI元素( MAPISendMail )中的一个函数调用将在Windows-32-bit-on-Windows-64-bit(WOW64)或Windows-64-上成功bit-on-Windows-32-bit(WOW32)场景,不会导致上述警报。此WOW64方案仅适用于Windows 7.图2显示了一个WOW64方案,其中32位MAPI应用程序在安装了64位Windows 7的计算机上调用 MAPISendMail 。在此方案中,MAPI库进行COM调用以启动64位Fixmapi应用程序。 Fixmapi应用程序隐式链接到MAPI库,该库将函数调用路由到Windows MAPI存根,后者又将调用转发到Outlook MAPI存根,从而使MAPISendMail函数调用成功。
因此,作为Delphi Jedi用户,他们的简单发送电子邮件功能将失败(因为他们使用太多 MAPI)。所以我必须创建自己的:
procedure MapiSimpleSendMail(slFiles: TStrings; ToEmailAddress: string=''; ToName: string='');
var
mapiMessage: TMapiMessage;
flags: LongWord;
// senderName: AnsiString;
// senderEmailAddress: AnsiString;
emailSubject: AnsiString;
emailBody: AnsiString;
// sender: TMapiRecipDesc;
recipients: packed array of TMapiRecipDesc;
attachments: packed array of TMapiFileDesc;
i: Integer;
hr: Cardinal;
es: string;
const
MAPI_E_UNICODE_NOT_SUPPORTED = 27; //Windows 8. The MAPI_FORCE_UNICODE flag is specified and Unicode is not supported.
begin
ZeroMemory(@mapiMessage, SizeOf(mapiMessage));
{ senderName := '';
senderEmailAddress := '';
ZeroMemory(@sender, sizeof(sender));
sender.ulRecipClass := MAPI_ORIG; //MAPI_TO, MAPI_CC, MAPI_BCC, MAPI_ORIG
sender.lpszName := PAnsiChar(senderName);
sender.lpszAddress := PAnsiChar(senderEmailAddress);}
mapiMessage.lpOriginator := nil; //PMapiRecipDesc; { Originator descriptor }
if ToEmailAddress <> '' then
begin
SetLength(recipients, 1);
recipients[0].ulRecipClass := MAPI_TO;
recipients[0].lpszName := LPSTR(ToName);
recipients[0].lpszAddress := LPSTR(ToEmailAddress);
mapiMessage.lpRecips := @recipients[0]; //A value of NULL means that there are no recipients. Additionally, when this member is NULL, the nRecipCount member must be zero.
mapiMessage.nRecipCount := 1;
end
else
begin
mapiMessage.lpRecips := nil; //A value of NULL means that there are no recipients. Additionally, when this member is NULL, the nRecipCount member must be zero.
mapiMessage.nRecipCount := 0;
end;
mapiMessage.lpszMessageType := nil;
if slFiles.Count > 0 then
begin
emailSubject := 'Emailing: ';
emailBody :=
' '+#13#10+ //Yes, the shell really does create a blank mail with a leading line of ten spaces
'Your message is ready to be sent with the following file or link attachments:'+#13#10;
SetLength(attachments, slFiles.Count);
for i := 0 to slFiles.Count-1 do
begin
attachments[i].ulReserved := 0; // Cardinal; { Reserved for future use (must be 0) }
attachments[i].flFlags := 0; // Cardinal; { Flags }
attachments[i].nPosition := $FFFFFFFF; //Cardinal; { character in text to be replaced by attachment }
attachments[i].lpszPathName := PAnsiChar(slFiles[i]); { Full path name of attachment file }
attachments[i].lpszFileName := nil; // LPSTR; { Original file name (optional) }
attachments[i].lpFileType := nil; // Pointer; { Attachment file type (can be lpMapiFileTagExt) }
if i > 0 then
emailSubject := emailSubject+', ';
emailSubject := emailSubject+ExtractFileName(slFiles[i]);
emailBody := emailBody+#13#10+
ExtractFileName(slFiles[i]);
end;
emailBody := emailBody+#13#10+
#13#10+
#13#10+
'Note: To protect against computer viruses, e-mail programs may prevent sending or receiving certain types of file attachments. Check your e-mail security settings to determine how attachments are handled.';
mapiMessage.lpFiles := @attachments[0];
mapiMessage.nFileCount := slFiles.Count;
end
else
begin
emailSubject := '';
emailBody := '';
mapiMessage.lpFiles := nil;
mapiMessage.nFileCount := 0;
end;
{
Subject
Emailing: 4388_888871544_MVM_10.tmp, amt3.log, swtag.log, wct845C.tmp, ~vs1830.sql
Body
<-- ten spaces
Your message is ready to be sent with the following file or link attachments:
4388_888871544_MVM_10.tmp
amt3.log
swtag.log
wct845C.tmp
~vs1830.sql
Note: To protect against computer viruses, e-mail programs may prevent sending or receiving certain types of file attachments. Check your e-mail security settings to determine how attachments are handled.
}
mapiMessage.lpszSubject := PAnsiChar(emailSubject);
mapiMessage.lpszNoteText := PAnsiChar(emailBody);
flags := MAPI_DIALOG;
hr := Mapi.MapiSendMail(0, 0, mapiMessage, flags, 0);
case hr of
SUCCESS_SUCCESS: {nop}; //The call succeeded and the message was sent.
MAPI_E_AMBIGUOUS_RECIPIENT:
begin
//es := 'A recipient matched more than one of the recipient descriptor structures and MAPI_DIALOG was not set. No message was sent.';
raise Exception.CreateFmt('Error %s sending e-mail message: %s', ['MAPI_E_AMBIGUOUS_RECIPIENT', SysErrorMessage(hr)]);
end;
MAPI_E_ATTACHMENT_NOT_FOUND:
begin
//The specified attachment was not found. No message was sent.
raise Exception.CreateFmt('Error %s sending e-mail message: %s', ['MAPI_E_ATTACHMENT_NOT_FOUND', SysErrorMessage(hr)]);
end;
MAPI_E_ATTACHMENT_OPEN_FAILURE:
begin
//The specified attachment could not be opened. No message was sent.
raise Exception.CreateFmt('Error %s sending e-mail message: %s', ['MAPI_E_ATTACHMENT_OPEN_FAILURE', SysErrorMessage(hr)]);
end;
MAPI_E_BAD_RECIPTYPE:
begin
//The type of a recipient was not MAPI_TO, MAPI_CC, or MAPI_BCC. No message was sent.
raise Exception.CreateFmt('Error %s sending e-mail message: %s', ['MAPI_E_BAD_RECIPTYPE', SysErrorMessage(hr)]);
end;
MAPI_E_FAILURE:
begin
//One or more unspecified errors occurred. No message was sent.
raise Exception.CreateFmt('Error %s sending e-mail message: %s', ['MAPI_E_FAILURE', SysErrorMessage(hr)]);
end;
MAPI_E_INSUFFICIENT_MEMORY:
begin
//There was insufficient memory to proceed. No message was sent.
raise Exception.CreateFmt('Error %s sending e-mail message: %s', ['MAPI_E_INSUFFICIENT_MEMORY', SysErrorMessage(hr)]);
end;
MAPI_E_INVALID_RECIPS:
begin
//One or more recipients were invalid or did not resolve to any address.
raise Exception.CreateFmt('Error %s sending e-mail message: %s', ['MAPI_E_INVALID_RECIPS', SysErrorMessage(hr)]);
end;
MAPI_E_LOGIN_FAILURE:
begin
//There was no default logon, and the user failed to log on successfully when the logon dialog box was displayed. No message was sent.
raise Exception.CreateFmt('Error %s sending e-mail message: %s', ['MAPI_E_LOGIN_FAILURE', SysErrorMessage(hr)]);
end;
MAPI_E_TEXT_TOO_LARGE:
begin
//The text in the message was too large. No message was sent.
raise Exception.CreateFmt('Error %s sending e-mail message: %s', ['MAPI_E_TEXT_TOO_LARGE', SysErrorMessage(hr)]);
end;
MAPI_E_TOO_MANY_FILES:
begin
//There were too many file attachments. No message was sent.
raise Exception.CreateFmt('Error %s sending e-mail message: %s', ['MAPI_E_TOO_MANY_FILES', SysErrorMessage(hr)]);
end;
MAPI_E_TOO_MANY_RECIPIENTS:
begin
//There were too many recipients. No message was sent.
raise Exception.CreateFmt('Error %s sending e-mail message: %s', ['MAPI_E_TOO_MANY_RECIPIENTS', SysErrorMessage(hr)]);
end;
MAPI_E_UNICODE_NOT_SUPPORTED:
begin
//The MAPI_FORCE_UNICODE flag is specified and Unicode is not supported.
//Note This value can be returned by MAPISendMailW only.
raise Exception.CreateFmt('Error %s sending e-mail message: %s', ['MAPI_E_UNICODE_NOT_SUPPORTED', SysErrorMessage(hr)]);
end;
MAPI_E_UNKNOWN_RECIPIENT:
begin
//A recipient did not appear in the address list. No message was sent.
raise Exception.CreateFmt('Error %s sending e-mail message: %s', ['MAPI_E_UNKNOWN_RECIPIENT', SysErrorMessage(hr)]);
end;
MAPI_E_USER_ABORT:
begin
es := 'The user canceled one of the dialog boxes. No message was sent.';
raise Exception.CreateFmt('Error %s sending e-mail message: %s', ['MAPI_E_USER_ABORT', es]);
end;
else
raise Exception.CreateFmt('Error %d sending e-mail message: %s', [hr, SysErrorMessage(hr)]);
end;
end;
注意:任何代码都会发布到公共域中。无需归属。