【问题标题】:How to save MailItem after sending发送后如何保存MailItem
【发布时间】:2017-04-12 10:54:00
【问题描述】:

我正在创建 MailItem:

    Application outlook = new Application();
    _mailItem = outlook.CreateItem(OIItemType.olMailItem);                
    Inspector inspector = _mailItem .GetInspector;
    inspector.Activate();     

设置收件人、正文等... 订阅发送事件:

    ((ItemEvents_10_Event)_mailItem).Send += MailItemSendHandler;

    void MailItemSendHandler(ref bool isSended) {
        _mailItem.SaveAs(filePath);
    }

当用户发送电子邮件时,我会保存它。但我的电子邮件以 compose 模式保存。如果我将在 OutLook 中打开它,我可以更改所有信息并重新发送。

如果我订阅 MailItem Inspector 关闭事件:

 ((InsPectorsEvents_10_Event)inspector).Close += CloseEventHandler;

在 CloseEventHandler 中保存 MailItem,我有一个错误:

“项目已被移动或删除”。

我的 MailItem 被发送并移动到“已发送邮件”Outlook 文件夹后,如何保存它? (以读取模式保存)

编辑

我正在使用 Items.AddItem 事件来保存我发送的 _mailItem。获取文件夹:

_sentFolderItems = _mailItem.SaveSentMessageFolder;

在 _addEventHandler 中订阅一些逻辑:

_sentFolderItems.Items.ItemAdd += _addEventHandler;

好:

  1. Outlook 主窗口正在运行。
  2. Outlook 进程显示在任务管理器中。
  3. 我正在生成 MailItem,向用户显示它。用户可以根据需要进行一些更改,然后按发送按钮。
    4。触发 Items.ItemAdd 并执行 _addEventHandler。
  4. Outlook 邮件窗口仍在运行,并且 Outlook 进程显示在任务管理器中。

不好:

Outlook 主窗口未运行,并且任务管理器中没有进程。 我正在生成 MailItem,为用户显示它。只为用户显示发送电子邮件的窗口。 Outlook 进程显示在任务管理器中。用户可以根据需要进行一些更改,然后按发送按钮。发送邮件并且任务管理器没有 OutLook 进程。 Items.ItemAdd 不会被触发并且 _addEventHandler 不会被执行。 但是发送的项目位于发送文件夹中。

 public class MailItemWrapper {
    public MailItemWrapper(MailItem mailItem, ComposeEmailWrapper composeEmailWrapper, bool isCompose) {
        _mailItem = mailItem;
        _identifyProperty = Guid.NewGuid();
        _mailItem.AddUserProperty(_identifyProperty.ToString(), _identifyProperty.ToString());
        _sentFolderItems = _mailItem.SaveSentMessageFolder;
        _inspector = _mailItem.GetInspector;
        _composeEmailWrapper = composeEmailWrapper;
        InComposeMode = isCompose;
        SetEventHandlers();
        Subscribe();
        _isSending = false;
    }

    private MailItem _mailItem;
    private Inspector _inspector;
    private MAPIFolder _sentFolderItems;
    private InspectorEvents_10_CloseEventHandler _closeEventHandler;
    private ItemEvents_10_SendEventHandler _sendEventHandler;
    private ItemsEvents_ItemAddEventHandler _addEventHandler;
    private readonly ComposeEmailWrapper _composeEmailWrapper;
    private string _path;
    private bool _isSending;
    private Guid _identifyProperty;

    public bool InComposeMode {
        get; set;
    }

    public MailItem MailItem {
        get {
            return _mailItem;
        }
    }

    public void Subscribe() {
        ((ItemEvents_10_Event) _mailItem).Send += _sendEventHandler;
        ((InspectorEvents_10_Event) _inspector).Close += _closeEventHandler;
        _sentFolderItems.Items.ItemAdd += _addEventHandler;
    }

    public void UnsubscribeAndRelease() {
        if(InComposeMode) {
            ((ItemEvents_10_Event) _mailItem).Send -= _sendEventHandler;
            ((InspectorEvents_10_Event) _inspector).Close -= _closeEventHandler;
            _sentFolderItems.Items.ItemAdd -= _addEventHandler;

            Marshal.ReleaseComObject(_sentFolderItems);
            Marshal.ReleaseComObject(_mailItem);
            Marshal.ReleaseComObject(_inspector);

            _sentFolderItems = null;
            _mailItem = null;
            _inspector = null;
            InComposeMode = false;
            _isSending = false;
        }
    }

    private void SetEventHandlers() {
        _sendEventHandler = (ref bool cancel) =>{           
            _isSending = true;
        };

        _addEventHandler = delegate (object item) {
            var mailItem = item as MailItem;
            if(mailItem != null) {
                var identityer = mailItem.UserProperties.Find(_identifyProperty.ToString());
                if(identityer != null && _identifyProperty.ToString() == identityer.Value) {
                    _path = mailItem.SaveAsInTempFolder(); // extension
                    if(_composeEmailWrapper != null && _composeEmailWrapper.Callback != null) {
                        System.Windows.Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (System.Action) ExecuteCallBack);
                        UnsubscribeAndRelease();
                    }
                }
                Marshal.ReleaseComObject(mailItem);
            }

        };

        _closeEventHandler = () => {
            // if user close dialog without sending => unsibscribe
            if(!_isSending) {
                UnsubscribeAndRelease();
            }
        };
    }

    private void ExecuteCallBack() {
        _composeEmailWrapper.Callback(_path, _composeEmailWrapper.SessionId);
    }
}

【问题讨论】:

  • 不是直接答案,因此是评论。但是如果您已经使用 MS-SQL Server,您可以查看 DBMail。如果您使用 DBMail,所有电子邮件都会自动保存在数据库中。
  • @RyanMann,我将电子邮件保存在 Windows 临时文件夹中(在客户端),然后将它们上传到服务器。我认为,直接使用 Outlook 电子邮件存储不是一个好主意。
  • 是的,我没有意识到这是一个 Outlook api 问题。我认为这是一个与网络应用相关的问题。

标签: c# email outlook interop mailitem


【解决方案1】:

在“已发送邮件”文件夹中使用Items.ItemAdd 事件。

【讨论】:

  • 感谢@DmitryStreblechenko 的回答。之后,我发现了一个类似的问题:stackoverflow.com/questions/12515612/…
  • 我使用 MailItem.SaveSentMessageFolder 进行订阅。但是当前景关闭时,此事件不会触发。
  • 我不确定你的意思。请出示您的代码。
  • 感谢您的帮助。我编辑了我的问题。也许会更清楚。
  • 不要将 _sentFolderItems 保存为全局/类变量。保存 _sentFolderItems.Items - 引发事件的对象必须是活动的。
猜你喜欢
  • 2020-06-08
  • 2010-12-24
  • 1970-01-01
  • 2013-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-04
  • 1970-01-01
相关资源
最近更新 更多