我遇到MAPI32.dll的MapiSendMail函数问题。一切似乎都很好,消息已经完成,然后我通过winapi函数发送它,并且我收到一个访问冲突错误,它发生在MAPISendMail中。这是代码的片段:
MAPIModule := LoadLibrary(PWideChar(MAPIDLL));
if MAPIModule = 0 then
Result := -1
else
try
@SM := GetProcAddress(MAPIModule, 'MAPISendMail');
if @SM <> nil then
begin
Result := SM(0, application.Handle, Msg, MAPI_DIALOG {or MAPI_LOGON_UI}, 0);
end
else
Result := 1;
finally
end;
我还试图将GetProcAddres更改为MAPISendMailW或MAPISendMailHelper,但是@SM是零。
@ EDIT1
function TMail._SendMAPIEmail(const aTo, aAtts: array of AnsiString; const body, subject, SenderName, SenderEmail: string; ShowError: Boolean = true): Integer;
var
SM: TFNMapiSendMail;
Msg: MapiMessage;
lpSender: MapiRecipDesc;
Recips: array of MapiRecipDesc;
Att: array of MapiFileDesc;
TempAttNames: array of pAnsiChar;
TempAttNamesAnsi: array of AnsiString;
TempAttPaths: array of pAnsiChar;
TempRecip: array of pAnsiChar;
p1, LenTo, LenAtts: Integer;
MAPIModule: HModule;
sError: String;
i: integer;
begin
try
FillChar(Msg, SizeOf(Msg), 0);
{ get the length of all arrays passed to this function }
LenTo := length(aTo);
if Trim(aAtts[0]) <> '' then
LenAtts := length(aAtts)
else
LenAtts := 0;
{ ... }
SetLength(Recips, LenTo);
SetLength(TempRecip, LenTo);
Setlength(Att, LenAtts);
SetLength(TempAttNames, LenAtts);
SetLength(TempAttPaths, LenAtts);
SetLength(TempAttNamesAnsi, LenAtts);
{ to }
for p1 := 0 to LenTo - 1 do
begin
FillChar(Recips[p1], SizeOf(Recips[p1]), 0);
Recips[p1].ulReserved := 0;
Recips[p1].ulRecipClass := MAPI_TO;
{ Upgrade }
Recips[p1].lpszName := '';
TempRecip[p1] := pAnsichar(aTo[p1]);
Recips[p1].lpszAddress := TempRecip[p1];
end;
{ atts }
for p1 := 0 to LenAtts - 1 do
begin
FillChar(Att[p1], SizeOf(Att[p1]), 0);
FillChar(TempAttPaths[p1], SizeOf(pAnsiChar), 0);
FillChar(TempAttNames[p1], SizeOf(pAnsiChar), 0);
FillChar(TempAttNamesAnsi[01], SizeOf(AnsiChar), 0);
Att[p1].ulReserved := 0;
Att[p1].flFlags := 0;
Att[p1].nPosition := Cardinal($FFFFFFFF);
{ Upgrade }
TempAttPaths[p1] := pAnsichar(aAtts[p1]);
Att[p1].lpszPathName := TempAttPaths[p1];
TempAttNamesAnsi[p1] := AnsiString((ExtractFileName(string(aAtts[p1]))));
TempAttNames[p1] := pAnsiChar(TempAttNamesAnsi[p1]);
Att[p1].lpszFileName := TempAttNames[p1];
end;
{ fill the message }
with Msg do
begin
ulReserved := 0;
if subject <> '' then
{ Upgrade }
lpszSubject := pAnsichar(AnsiString(subject));
if body <> '' then
{ Upgrade }
lpszNoteText := pAnsichar(AnsiString(body));
if SenderEmail <> '' then
begin
lpSender.ulRecipClass := MAPI_ORIG;
if SenderName = '' then
lpSender.lpszName := pAnsichar(AnsiString(SenderEmail))
else
lpSender.lpszName := pAnsichar(AnsiString(SenderName));
lpSender.lpszAddress := pAnsichar(AnsiString(SenderEmail));
lpSender.ulEIDSize := 0;
lpSender.lpEntryID := nil;
lpOriginator := @lpSender;
end
else
Msg.lpOriginator := nil;
Msg.lpszMessageType := nil;
Msg.lpszDateReceived := nil;
Msg.lpszConversationID := nil;
Msg.flFlags := 0;
Msg.nRecipCount := LenTo;
Msg.lpRecips := @Recips[0];
Msg.nFileCount := LenAtts;
Msg.lpFiles := @Att[0];
end;
MAPIModule := LoadLibrary(PWideChar(MAPIDLL));
if MAPIModule = 0 then
Result := -1
else
try
@SM := GetProcAddress(MAPIModule, 'MAPISendMail');
if @SM <> nil then
begin
//Result := MapiSendMail(0, application.Handle, Msg, MAPI_DIALOG, 0);
Result := SM(0, 0, Msg, MAPI_DIALOG {or MAPI_LOGON_UI}, 0);
end
else
Result := 1;
finally
if Assigned(Att) and (Msg.nFileCount > 0) then
begin
for i := 0 to Msg.nFileCount - 1 do
begin
if Assigned(Att[i].lpszPathName) then
Att[i].lpszPathName := nil;
if Assigned(Att[i].lpszFileName) then
Att[i].lpszFileName := nil;
//FreeMem(Att[i].lpszPathName);
//Dispose(Att[i].lpszPathname);
//StrDispose(Att[i].lpszPathName);
//Dispose(Att[i].lpszFileName);
//StrDispose(Att[i].lpszFileName);
end;
Att := nil;
end;
if Assigned(Recips) and (Msg.nRecipCount > 0) then
begin
for i := 0 to Msg.nRecipCount - 1 do
begin
if Assigned(Recips[i].lpszName) then
Recips[i].lpszName := nil;
if Assigned(Recips[i].lpszAddress) then
Recips[i].lpszAddress := nil;
//if Assigned(Recips[i].lpszName) then
//Dispose(Recips[i].lpszName);
//if Assigned(Recips[i].lpszAddress) then
//Dispose(Recips[i].lpszAddress);
end;
Recips := nil;
end;
end;
答案 0 :(得分:0)
在Win32下它应该不是问题。首先尝试使用非常简单的MapiMessage调用MapiSendMail,如果它可以工作,一点一点地增加复杂性。您的代码太复杂,无法直观地调试它。您是否使用非常简单的MapiMessage调用MapiSendMail,仅用于测试?请尝试以下代码,它确实有效:
procedure TestSendExA(const APath1, ACaption1, APath2, ACaption2: AnsiString);
var
R: Integer;
MSG: TMapiMessage;
F: Array [0..1] of TMapiFileDesc;
Recipients: array[0..1] of TMapiRecipDesc;
Originator : array[0..0] of TMapiRecipDesc;
begin
if not FileExists(APath1) or not FileExists(APath2) then raise Exception.Create('File not found');
FillChar(Msg, SizeOf(Msg), 0);
Msg.lpszSubject := 'testo';
Msg.lpszNoteText := 'Hi there!';
Msg.lpszDateReceived := '2015/01/25 12:34';
Msg.lpszConversationId := '1234.test@ritlabs.com';
Msg.flFlags := MAPI_RECEIPT_REQUESTED;
FillChar(Recipients, SizeOf(Recipients), 0);
with Recipients[0] do
begin
ulRecipClass := MAPI_TO;
lpszName := 'Maxim Masiutin';
lpszAddress := 'maxim.test@ritlabs.com';
end;
with Recipients[1] do
begin
ulRecipClass := MAPI_CC;
lpszName := 'Vasilii Pupkin';
lpszAddress := 'pupkin.test@ritlabs.com';
end;
FillChar(Originator, SizeOf(Originator), 0);
with Originator[0] do
begin
ulRecipClass := MAPI_TO;
lpszName := 'Maxim Masiutin';
lpszAddress := 'max@ritlabs.com';
end;
Msg.lpOriginator := @Originator;
Msg.nRecipCount := 2;
Msg.lpRecips := @Recipients;
Msg.nFileCount := 2;
Msg.lpFiles := @F;
FillChar(F, SizeOf(F), 0);
F[0].lpszPathName := PAnsiChar(APath1);
F[0].lpszFileName := PAnsiChar(ACaption1);
F[1].lpszPathName := PAnsiChar(APath2);
F[1].lpszFileName := PAnsiChar(ACaption2);
R := MAPISendMail(MapiSession, 0, Msg, 0, 0);
end;
上例中的MapiSession是MapiLogon返回的会话句柄。
此示例代码要求您将两个有效文件路径传递给APath1和APath2中的有效文件。
当您使用Delphi的简单MAPI时,MapiMessage和其他记录的记录对齐非常重要:(1)确保记录没有&#34;打包&#34;字首; (2)确保在第一个记录定义之前显式指定{$ A8}编译器指令。这在Win32和Win64下都能正常工作。