MailItem.Sent在检查用户是否已发送邮件时给出错误“项目被移动或删除”

时间:2015-05-20 09:50:30

标签: c# outlook mailitem

执行以下代码时,错误显示为the item is moved or deleted

Outlook.Application outlookApp = new Outlook.Application();
Outlook.MailItem mailItem = (Outlook.MailItem)outlookApp.CreateItem(Outlook.OlItemType.olMailItem);
mailItem.Subject = mailSubject;
mailItem.To = "";
mailItem.CC = "";
mailItem.Attachments.Add(totalPath);
mailItem.Body = mailBody;
mailItem.Importance = Outlook.OlImportance.olImportanceNormal;
mailItem.Display(true);
//Mail is send succesfully?
Bool sent = true;
if (!mailItem.Sent)
{
   sent = false;
}

检查mailItem.Sent属性时会出现错误。

我的问题是.Sent如何运作?我正在尝试向最终用户显示电子邮件,然后检查他们是否已发送电子邮件。

2 个答案:

答案 0 :(得分:1)

调用Display方法(传递true)后,邮件项可能不再存在。它可以移动到“发件箱”文件夹,以便通过传输提供进一步处理。

Sent属性设置一次而不是您要查找的内容。此外,在调用Display方法后立即检查Sent属性值不是一个好主意。邮件项目可以标记为由传输提供商处理,尚未发送。相反,您需要在代码中处理ItemSend事件。但检查主题行不是一个稳定的解决方案。至少用户可以在显示检查器窗口时更改预设值。

在调用MailItem类的display方法之前,您可以将一个用户属性(您自己的ID)添加到MailItem。然后在ItemSend事件处理程序中,您可以检出该值并在需要时将其删除。因此,您可以确定该项目将被发送(而不是实际发送)。

如果您需要确保邮件项目已发送,我建议您处理Items类的ItemAdd事件(请参阅Folder类的相应属性)。例如,发送Outlook项目时,已发送的副本将放置到Outlook中的“已发送邮件”文件夹中。您可以处理该文件夹的ItemAdd事件,以确保该项目是肯定发送的。考虑在显示Outlook项目之前添加用户属性,并在ItemAdd事件处理程序中检查它以唯一地标识该项目。

请注意,您可以指定自定义文件夹放置已发送邮件的位置。 MailItem类的SaveSentMessageFolder属性允许设置一个Folder对象,该对象表示发送后将保存电子邮件副本的文件夹。因此,您可以将已发送的邮件移动到您自己的自定义文件夹中。

答案 1 :(得分:0)

这就是我解决这个问题的方法:

type
  TOutlookFolderItemsEvent = procedure(ASender: TObject; const Item: IDispatch) of object;
  TOutlookFolderItems = class(TOleServer)
  private
    FIntf: _Items;
    FOnItemAdd: TOutlookFolderItemsEvent;
  protected
    procedure InitServerData; override;
    procedure InvokeEvent(DispID: TDispID; var Params: TVariantArray); override;
  public
    procedure Disconnect; override;
    procedure Connect; override;
    procedure ConnectTo(svrIntf: _Items);

    property OnItemAdd: TOutlookFolderItemsEvent read FOnItemAdd write FOnItemAdd;
  end;

  TMyForm = class(TForm)
    OutlookApplication1: TOutlookApplication;
  private
    FMyEntryID: String;
    FItems: TOutlookFolderItems;
    procedure ItemsItemAdd(ASender: TObject; const Item: IDispatch);
    procedure MySendEmail;
  end;

procedure TMyForm.MySendEmail;
var
  Mi: MailItem;
  EntryID: TGUID;
begin
  OutlookApplication1.Disconnect;
  OutlookApplication1.Connect;
  OutlookApplication1.Application.ActiveExplorer.WindowState := olMaximized;

  CreateGuid(EntryID);
  FMyEntryID:= GUIDToString(EntryID);
  Mi.UserProperties.Add('MyEntryID', olText, True, olText).Value := FMyEntryID;

  Mi.Save;
  Mi.Display(0);

  // Add the following code to OutlookApplication's OnItemSend
  // to get a more accurate SaveSentMessageFolder
  // (as it may change when selecting from different From accounts)
  FItems := TOutlookFolderItems.Create(Self);
  FItems.ConnectTo(Mi.SaveSentMessageFolder.Items);
  FItems.OnItemAdd := ItemsItemAdd;
end;

procedure TMyForm.ItemsItemAdd(ASender: TObject; const Item: IDispatch);
var
  S: String;
  I: MailItem;
  P: UserProperty;
begin
  I := Item as MailItem;

  P := I.UserProperties.Find('MyEntryID', True);

  if (P = nil) or (P.Value <> FMyEntryID) then Exit; // Not the email we're waiting for

  // MailItem is known to be sent and in SentFolders here.
  // Add here any relevant code.
end;

{ TOutlookFolderItems }

procedure TOutlookFolderItems.Connect;
begin
end;

procedure TOutlookFolderItems.ConnectTo(svrIntf: _Items);
begin
  Disconnect;
  FIntf := svrIntf;
  ConnectEvents(FIntf);
end;

procedure TOutlookFolderItems.Disconnect;
begin
  if Fintf <> nil then
  begin
    DisconnectEvents(FIntf);
    FIntf := nil;
  end;
end;

procedure TOutlookFolderItems.InitServerData;
const
  CServerData: TServerData = (
    ClassID:   '{00063052-0000-0000-C000-000000000046}';
    IntfIID:   '{00063041-0000-0000-C000-000000000046}';
    EventIID:  '{00063077-0000-0000-C000-000000000046}';
    LicenseKey: nil;
    Version: 500);
begin
  ServerData := @CServerData;
end;

procedure TOutlookFolderItems.InvokeEvent(DispID: TDispID; var Params: TVariantArray);
begin
  case DispID of
    -1: Exit;  // DISPID_UNKNOWN
    61441: if Assigned(FOnItemAdd) then
         FOnItemAdd(Self, Params[0] {const IDispatch});
  end;
end;