Ian*_*oyd 5 mapi winapi windows-shell
给定一些文件(或 shell 文件对象),我如何使用.MAPIMail它们调用注册的 shell 扩展处理程序?
我的计算机上有一些文件:
C:\Users\ian\AppData\Local\Temp\Contoso_Invoice_141174.pdfC:\Users\ian\AppData\Local\Temp\Contoso_Invoice_141173.pdfC:\Users\ian\AppData\Local\Temp\Contoso_Invoice_141171.pdf我想做的编程相当于将它们放在.MAPIMail注册的处理程序上:

发送到文件夹的邮件收件人选项实际上是一个特殊的注册.MAPIMail扩展:

这是在系统上注册的文件类型:
HKEY_CLASSES_ROOT\.mapimail
Run Code Online (Sandbox Code Playgroud)
如何调用临时.mapimail文件上的放置?
现在,我可能是一个糟糕的开发人员,并且拼写了注册表,该条目的.mapimail默认值:
CLSID\{9E56BE60-C50F-11CF-9A2C-00A0C90A90CE}
Run Code Online (Sandbox Code Playgroud)
提取 clsid {9E56BE60-C50F-11CF-9A2C-00A0C90A90CE},并确认该类已注册:
HKEY_CLASSES_ROOT\CLSID\{9E56BE60-C50F-11CF-9A2C-00A0C90A90CE}
(default) = Desktop Shortcut
\InProcServer32
(default) = %SystemRoot%\System32\sendmail.dll
Run Code Online (Sandbox Code Playgroud)
并用于CoCreateInstance创建该 COM 对象:
IUnknown unk = CreateComObject("{9E56BE60-C50F-11CF-9A2C-00A0C90A90CE}");
Run Code Online (Sandbox Code Playgroud)
然后我处于一个无文档、不受支持的世界,我不知道我必须使用什么接口QueryInterface,也不知道以什么顺序调用什么方法。
我想要的是可能涉及外壳的东西(伪代码):
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);
Run Code Online (Sandbox Code Playgroud)
除了所有代码都依赖于上下文菜单的存在,而我没有。没有人说.MAPIMail必须在任何上下文中发送到菜单。
我问的是如何将文件放到一个.mapimail文件上。
还有我的上帝。
因为当您是在安装了 Office 64 位的 Windows 64 位上运行的 32 位应用程序时,不会安装 MAPI 客户端。所以我需要能够完成用户已经可以完成的事情。
虽然它没有回答我的问题,但雷蒙德指出这是一个愚蠢的问题。任何心智正常的人都不应该尝试向收件人发送邮件。但我很绝望!
事实证明我并没有完全陷入困境。虽然从 32 位应用程序处理 64 位 Outlook(MAPI 提供程序)时会出现位数噩梦(反之亦然),但还是有一个解决方案。
如果我只 MapiSendMail使用,而不使用其他MAPI 函数,那么跨越 32 位/64 位障碍是安全的。来自在 32 位和 64 位平台上构建 MAPI 应用程序:
32 位 MAPI 应用程序和 64 位 Outlook
不支持在安装有 64 位 Outlook 和 64 位 Windows 的计算机上运行 32 位 MAPI 应用程序。应用程序开发人员必须将应用程序更新并重建为适用于 64 位平台的 64 位应用程序。这是因为 32 位应用程序无法加载 64 位 Msmapi32.dll 文件。应用程序开发人员必须进行少量 API 更改才能成功地为 64 位环境构建代码。MAPI 头文件已通过这些更改进行更新,以支持 64 位平台。您可以在Outlook 2010:MAPI 头文件下载这些头文件。开发人员可以使用同一组 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 存根,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;
Run Code Online (Sandbox Code Playgroud)
注意:任何代码都会发布到公共领域。无需归属。
| 归档时间: |
|
| 查看次数: |
2714 次 |
| 最近记录: |