新版Outlook编程发带附件邮件遇异常:OLE报错、ShellExecute无附件
解决新版Outlook的邮件发送问题
一、OLE方式报错“Invalid class string”的解决
你遇到的OLE创建失败问题,不一定是ProgID变更,大概率是新版Outlook的COM组件未正确注册,或者存在位数不匹配的情况,可按以下步骤排查:
- 检查位数匹配:确保你的应用和Outlook是同位数(32位/64位)。如果应用是32位,而Outlook是64位,反之亦然,会导致COM调用失败。可在Outlook的「文件」-「Office账户」-「关于Outlook」中查看位数信息,调整应用编译位数或重新安装对应位数的Office。
- 重新注册COM组件:以管理员身份打开命令提示符,根据你的Outlook安装路径执行注册命令:
(如果是Office 365家庭/个人版,路径可能类似,可自行查找OUTLOOK.EXE的位置)regsvr32.exe "C:\Program Files\Microsoft Office\root\Office16\OUTLOOK.EXE" - 尝试指定具体版本的ProgID:如果上述步骤无效,尝试将代码中的ProgID改为
Outlook.Application.16,即:Outlook:=CreateOleObject('Outlook.Application.16') ;
二、ShellExecute的mailto无附件问题
mailto协议的attachment参数并非标准协议内容,新版Outlook已不再支持该参数,所以无法通过这种方式添加附件。推荐改用以下两种可靠方案:
方案1:修复OLE后继续使用OLE添加附件
如果OLE方式修复成功,可通过以下代码(以Delphi为例)创建带附件的邮件:
var Outlook, MailItem: OleVariant; begin Outlook := CreateOleObject('Outlook.Application'); MailItem := Outlook.CreateItem(0); // 0代表olMailItem MailItem.To := recipient_email_address; MailItem.Subject := subject; MailItem.Body := body; MailItem.Attachments.Add(attachment_path); MailItem.Display; // 显示邮件窗口,若要直接发送可改为MailItem.Send; end;
方案2:使用MAPI函数发送
如果OLE方式仍无法使用,可调用Windows的MAPI函数MAPISendMail来实现带附件的邮件发送,示例代码(Delphi):
uses MAPI; function SendMailWithAttachment(const Recipient, Subject, Body, Attachment: string): Boolean; var MapiMessage: TMapiMessage; MapiRecip: TMapiRecipDesc; MapiFile: TMapiFileDesc; begin ZeroMemory(@MapiMessage, SizeOf(TMapiMessage)); ZeroMemory(@MapiRecip, SizeOf(TMapiRecipDesc)); ZeroMemory(@MapiFile, SizeOf(TMapiFileDesc)); MapiMessage.lpszSubject := PChar(Subject); MapiMessage.lpszNoteText := PChar(Body); MapiRecip.lpszName := PChar(Recipient); MapiRecip.lpszAddress := PChar('SMTP:' + Recipient); MapiRecip.ulRecipClass := MAPI_TO; MapiMessage.nRecipCount := 1; MapiMessage.lpRecips := @MapiRecip; MapiFile.lpszPathName := PChar(Attachment); MapiFile.lpszFileName := PChar(ExtractFileName(Attachment)); MapiMessage.nFileCount := 1; MapiMessage.lpFiles := @MapiFile; Result := MAPISendMail(0, 0, @MapiMessage, MAPI_DIALOG, 0) = SUCCESS_SUCCESS; end;
调用时直接执行SendMailWithAttachment(recipient_email_address, subject, body, attachment_path);即可,该方式兼容性更强,不受Outlook版本影响。
内容的提问来源于stack exchange,提问作者peter
相关产品推荐
相关产品推荐

