如何将带有附件的 MAPI 电子邮件发送给传真收件人?

发布于 2024-07-30 10:02:10 字数 4918 浏览 9 评论 0原文

我正在使用此方法发送带有 PDF 附件的 MAPI 电子邮件从 Delphi 应用程序内部。

它会打开一个 MS Outlook“新消息”窗口,其中已附加 pdf 文档和一个空白收件人。

如果您输入普通的电子邮件联系方式,那么一切都会顺利进行。

但是,如果您选择传真收件人,它会出现在我的“已发送邮件”文件夹中,但传送会失败(没有错误,没有 MS Outlook“传送失败”消息,并且不会传送消息)。

“传真收件人”是在 MS Outlook 中设置的,只有一个传真号码。 没有电子邮件或任何东西。 我们使用 faxcore 服务器 将这些“传真”路由到 Outlook 收件箱。

如果您查看此图片,我唯一的字段我为此联系人填写的是标有“商务传真”的联系人。

如果我手动(即在我的应用程序之外)创建标准的 MS Outlook 电子邮件并选择完全相同的传真收件人,并手动附加完全相同的 PDF,那么一切都会顺利进行。

因此,使用 MAPI 发送传真号码似乎会导致失败。 这篇文章听起来很相似,除了他们收到“消息无法送达”错误,而我没有t.

有人可以给我一些建议吗?

谢谢

更新:如果我使用 MAPI 创建电子邮件,然后手动删除附件,那么它确实可以工作。 因此,在 Outlook 中,我可以通过电子邮件将附件发送给传真收件人,但使用 MAPI 会失败。

完整源码如下:

unit Main;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    function SendEMailUsingMAPI(const Subject, Body, FileName, SenderName,
      SenderEMail, RecipientName, RecipientEMail: string): integer;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

uses
  Mapi;

procedure TForm1.Button1Click(Sender: TObject);
begin
  //this will bring up an MS Outlook dialog.
  //inside that dialog, if i choose a normal email recipient, it works.
  //                    if i choose a fax recipient, it fails silently.
  //if i create the email from w/in outlook, it can go to *either* with success.

  SendEmailUsingMAPI(
    'Subject',  //subject of email
    'Body',  //body of email text
    'c:\my_doc.pdf',  //attachment file name
    'My name',  //sender email name
    '[email protected]',  //sender email address
    '',  //recipient email name
    '');  //recipient email address
end;


function TForm1.SendEMailUsingMAPI(const Subject, Body, FileName, SenderName,
  SenderEMail, RecipientName, RecipientEMail: string): Integer;
var
  Message: TMapiMessage;
  lpSender, lpRecipient: TMapiRecipDesc;
  FileAttach: TMapiFileDesc;
  SM: TFNMapiSendMail;
  MAPIModule: HModule;
  FileType: TMapiFileTagExt;
begin
  FillChar(Message,SizeOf(Message),0);

  if (Subject <> '') then begin
    Message.lpszSubject := PChar(Subject);
  end;

  if (Body <> '') then begin
    Message.lpszNoteText := PChar(Body);
  end;

  if (SenderEmail <> '') then
  begin
    lpSender.ulRecipClass := MAPI_ORIG;
    if (SenderName = '') then begin
      lpSender.lpszName := PChar(SenderEMail);
    end
    else begin
      lpSender.lpszName := PChar(SenderName);
    end;
    lpSender.lpszAddress := PChar(SenderEmail);
    lpSender.ulReserved := 0;
    lpSender.ulEIDSize := 0;
    lpSender.lpEntryID := nil;
    Message.lpOriginator := @lpSender;
  end;

  if (RecipientEmail <> '') then begin
    lpRecipient.ulRecipClass := MAPI_TO;
    if (RecipientName = '') then begin
      lpRecipient.lpszName := PChar(RecipientEMail);
    end
    else begin
      lpRecipient.lpszName := PChar(RecipientName);
    end;
    lpRecipient.lpszAddress := PChar(RecipientEmail);
    lpRecipient.ulReserved := 0;
    lpRecipient.ulEIDSize := 0;
    lpRecipient.lpEntryID := nil;
    Message.nRecipCount := 1;
    Message.lpRecips := @lpRecipient;
  end
  else begin
    Message.lpRecips := nil;
  end;

  if (FileName = '') then begin
    Message.nFileCount := 0;
    Message.lpFiles := nil;
  end
  else begin
    FillChar(FileAttach,SizeOf(FileAttach),0);
    FileAttach.nPosition := Cardinal($FFFFFFFF);
    FileAttach.lpszPathName := PChar(FileName);

    FileType.ulReserved := 0;
    FileType.cbEncoding := 0;
    FileType.cbTag := 0;
    FileType.lpTag := nil;
    FileType.lpEncoding := nil;

    FileAttach.lpFileType := @FileType;
    Message.nFileCount := 1;
    Message.lpFiles := @FileAttach;
  end;

  MAPIModule := LoadLibrary(PChar(MAPIDLL));

  if MAPIModule = 0 then begin
    Result := -1;
  end
  else begin
    try
      @SM := GetProcAddress(MAPIModule,'MAPISendMail');
      if @SM <> nil then begin
        Result := SM(0,Application.Handle,Message,
          MAPI_DIALOG or MAPI_LOGON_UI,0);
      end
      else begin
        Result := 1;
      end;
    finally
      FreeLibrary(MAPIModule);
    end;
  end;

  if Result <> 0 then begin
    MessageDlg('Error sending mail ('+IntToStr(Result)+').',mtError,[mbOK],0);
  end;
end;

end.

I am using this method to send a MAPI email with a PDF attachment from inside a Delphi application.

It brings up an MS Outlook "new message" window with the pdf document already attached, and a blank recipient.

If you type in a normal email contact, then it goes through fine.

However, if you select a fax recipient, it appears in my "Sent Items" folder, but delivery fails silently (no error, no MS Outlook "delivery failed" message, and no delivery of the message).

The "fax recipient" is set up in MS Outlook with nothing but a fax number. No email or anything. We use a faxcore server to route these "faxes" to the outlook inbox.

If you look at this image, the only field I've filled in for this contact is the one labeled "Business Fax".

If I manually (i.e., outside of my application) create a standard MS Outlook email and choose the very same fax recipient, and manually attach the very same PDF, then it goes through fine.

So it seems that something about using MAPI to send to a fax number causes it to fail.
This post sounds similar, except they get a "message undeliverable" error and I don't.

Can anyone give me some pointers on this?

Thanks

Update: If I use MAPI to create the email, but then I manually delete the attachment, then it does work. So from within outlook, I can email an attachment to a fax recipient, but using MAPI it fails.

Complete source code follows:

unit Main;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    function SendEMailUsingMAPI(const Subject, Body, FileName, SenderName,
      SenderEMail, RecipientName, RecipientEMail: string): integer;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

uses
  Mapi;

procedure TForm1.Button1Click(Sender: TObject);
begin
  //this will bring up an MS Outlook dialog.
  //inside that dialog, if i choose a normal email recipient, it works.
  //                    if i choose a fax recipient, it fails silently.
  //if i create the email from w/in outlook, it can go to *either* with success.

  SendEmailUsingMAPI(
    'Subject',  //subject of email
    'Body',  //body of email text
    'c:\my_doc.pdf',  //attachment file name
    'My name',  //sender email name
    '[email protected]',  //sender email address
    '',  //recipient email name
    '');  //recipient email address
end;


function TForm1.SendEMailUsingMAPI(const Subject, Body, FileName, SenderName,
  SenderEMail, RecipientName, RecipientEMail: string): Integer;
var
  Message: TMapiMessage;
  lpSender, lpRecipient: TMapiRecipDesc;
  FileAttach: TMapiFileDesc;
  SM: TFNMapiSendMail;
  MAPIModule: HModule;
  FileType: TMapiFileTagExt;
begin
  FillChar(Message,SizeOf(Message),0);

  if (Subject <> '') then begin
    Message.lpszSubject := PChar(Subject);
  end;

  if (Body <> '') then begin
    Message.lpszNoteText := PChar(Body);
  end;

  if (SenderEmail <> '') then
  begin
    lpSender.ulRecipClass := MAPI_ORIG;
    if (SenderName = '') then begin
      lpSender.lpszName := PChar(SenderEMail);
    end
    else begin
      lpSender.lpszName := PChar(SenderName);
    end;
    lpSender.lpszAddress := PChar(SenderEmail);
    lpSender.ulReserved := 0;
    lpSender.ulEIDSize := 0;
    lpSender.lpEntryID := nil;
    Message.lpOriginator := @lpSender;
  end;

  if (RecipientEmail <> '') then begin
    lpRecipient.ulRecipClass := MAPI_TO;
    if (RecipientName = '') then begin
      lpRecipient.lpszName := PChar(RecipientEMail);
    end
    else begin
      lpRecipient.lpszName := PChar(RecipientName);
    end;
    lpRecipient.lpszAddress := PChar(RecipientEmail);
    lpRecipient.ulReserved := 0;
    lpRecipient.ulEIDSize := 0;
    lpRecipient.lpEntryID := nil;
    Message.nRecipCount := 1;
    Message.lpRecips := @lpRecipient;
  end
  else begin
    Message.lpRecips := nil;
  end;

  if (FileName = '') then begin
    Message.nFileCount := 0;
    Message.lpFiles := nil;
  end
  else begin
    FillChar(FileAttach,SizeOf(FileAttach),0);
    FileAttach.nPosition := Cardinal($FFFFFFFF);
    FileAttach.lpszPathName := PChar(FileName);

    FileType.ulReserved := 0;
    FileType.cbEncoding := 0;
    FileType.cbTag := 0;
    FileType.lpTag := nil;
    FileType.lpEncoding := nil;

    FileAttach.lpFileType := @FileType;
    Message.nFileCount := 1;
    Message.lpFiles := @FileAttach;
  end;

  MAPIModule := LoadLibrary(PChar(MAPIDLL));

  if MAPIModule = 0 then begin
    Result := -1;
  end
  else begin
    try
      @SM := GetProcAddress(MAPIModule,'MAPISendMail');
      if @SM <> nil then begin
        Result := SM(0,Application.Handle,Message,
          MAPI_DIALOG or MAPI_LOGON_UI,0);
      end
      else begin
        Result := 1;
      end;
    finally
      FreeLibrary(MAPIModule);
    end;
  end;

  if Result <> 0 then begin
    MessageDlg('Error sending mail ('+IntToStr(Result)+').',mtError,[mbOK],0);
  end;
end;

end.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

只是在用心讲痛 2024-08-06 10:02:10

好的,您的更新指向附件,所以我将提出另一个猜测:尝试将附件的文件类型明确设置为“application/pdf”(您当前的代码未设置 lpFileType 字段)。 传真处理可能取决于此。 您可以将 MapiFileTagExt 的编码部分(lpFileType 指向的类型)留空,只需 FillChar 记录并设置 cbTag 和 lpTag 字段。

如果你需要代码(mapi 结构有时可能有点令人眼花缭乱),就大喊吧,但我需要一些时间才能找到时间来输入它。无论如何,再说一次,我只是猜测。 我的家庭环境中没有传真设置,否则我会做一些适当的测试。

编辑

说明下面的代码。 但是,从那以后我检查了 Outlook Spy,无论使用哪种方法,还是手动附加文件时,PR_ATTACH_MIME_TAG 属性似乎都是在发送的项目上设置的,而仅在生成的传入消息上设置。

  FillChar(FileAttach,SizeOf(FileAttach),0);
  FileAttach.nPosition := Cardinal($FFFFFFFF);
  FileAttach.lpszPathName := PChar(FileName);
  //
  MimeType := 'application/pdf'; 
  //
  FileType.ulReserved := 0;
  FileType.cbTag := Length( MimeType );
  FileType.lpTag := PByte(MimeType);
  FileType.cbEncoding := 0;
  FileType.lpEncoding := nil;
  //
  FileAttach.lpFileType := @FileType;
  Message.nFileCount := 1;
  Message.lpFiles := @FileAttach;

(代码格式化程序并不是特别有用)。

Ok, your update points towards the attachment, so I'm going to put in another guess: try setting the filetype of the attachment explicitly to 'application/pdf' (your current code doesn't set the lpFileType field). The fax handling might be dependent on that. You can just leave the encoding parts of the MapiFileTagExt (the type lpFileType points to) blank, simply FillChar the record and set cbTag and lpTag fields.

If you need code (the mapi structures can be a bit dazzling at times) just yell, but it'll take me some time to find a moment to type it up.. And anyway, again, I'm just guessing. I don't have a fax setup in my home environment, otherwise I'd do some proper testing.

EDIT

Illustrating bit of code below. However, I've since then checked with Outlook Spy, and with neither method, nor when attaching a file manually, the PR_ATTACH_MIME_TAG property seems to be set on the sent item, only on the resulting incoming message.

  FillChar(FileAttach,SizeOf(FileAttach),0);
  FileAttach.nPosition := Cardinal($FFFFFFFF);
  FileAttach.lpszPathName := PChar(FileName);
  //
  MimeType := 'application/pdf'; 
  //
  FileType.ulReserved := 0;
  FileType.cbTag := Length( MimeType );
  FileType.lpTag := PByte(MimeType);
  FileType.cbEncoding := 0;
  FileType.lpEncoding := nil;
  //
  FileAttach.lpFileType := @FileType;
  Message.nFileCount := 1;
  Message.lpFiles := @FileAttach;

(code-formatter is not being particularly helpful).

魔法唧唧 2024-08-06 10:02:10

是否传真地址在 0(临时)会话中不可用? 换句话说,首先使用 MAPILogon 登录会话,然后在 MAPISendMail 调用中提供 hSession 有帮助吗?

Could it be the fax addresses are not available in the 0 (temporary) session? In other words, does logging into a session using MAPILogon first, then providing the hSession in the MAPISendMail call help?

缪败 2024-08-06 10:02:10

您可以尝试启用 Outlook 传输日志记录,希望那里会出现一些(任何)错误消息。 确保首先记录手动传真(工作情况),以检查此日志中是否确实显示了任何相关内容。

不幸的是,我个人通过此日志解决问题的成功率为零,但尝试获取更多信息总没有坏处,对吧?

You could try enabling Outlook Transport Logging, hopefully some (any) error message will turn up there. Make sure to log a manual fax (working situation) first, to check if anything related actually does show up in this log.

Unfortunately, my personal success rate in solving issues through this log is zilch, but trying to get more information never hurts, right?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文