如何从C#中的Outlook仅保存Excel附件?

时间:2019-07-16 23:37:36

标签: c# excel outlook windows-services

我必须创建一个程序来保存邮件收件箱中的Excel附件。 目前,我正在通过事件处理程序保存来自传入邮件的所有附件,但似乎该事件并非总是触发的,而是仅触发4个邮件中的3个。我也不知道原因。

因此,我正在考虑遍历收件箱中的邮件,查找具有特定主题标题的邮件并保存附加的Excel文件。

但是我该怎么做?其他解决方案仅通过加载项显示,但我想为此使用Windows服务。

到目前为止,我的代码(尽管每次都无法正常运行,也许有人知道原因吗?)

public partial class MyService : ServiceBase
{
        public string AttachPath = @"[mypath to save attachments]";

        public MyService()
        {
            InitializeComponent();
        }

        public void RunAsConsole(string[] args)
        {
            Console.WriteLine("This service is executed as a console application.");
            Console.WriteLine("Application active.");
            OnStart(args);
            Console.WriteLine("Press q to exit.");
            string userInput = Console.ReadLine();

            while (userInput != "q")
            {
                userInput = Console.ReadLine();
            }

            Console.WriteLine("Finished! \nPress any key to exit...");
            Console.ReadLine();
            OnStop();
        }

        protected override void OnStart(string[] args)
        {
            Outlook.NameSpace outlookNameSpace;
            Outlook.MAPIFolder inbox;
            Outlook.Items items;

            Outlook.Application oApp = new Outlook.Application();
            outlookNameSpace = oApp.GetNamespace("MAPI");
            inbox = outlookNameSpace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderInbox);

            items = inbox.Items;
            items.ItemAdd +=
                new Outlook.ItemsEvents_ItemAddEventHandler(items_ItemAdd);
        }

        void items_ItemAdd(object Item)
        {
            string filter = "[myFilter]";
            Outlook.MailItem mail = (Outlook.MailItem)Item;

            if (Item != null)
            {
                if (mail.Subject.ToUpper().Contains(filter.ToUpper()))
                {
                    Console.WriteLine(DateTime.Now.ToShortTimeString() + " Mail found!: " + mail.Subject);

                    if (mail.Attachments.Count > 0)
                    {
                        for (int i = 1; i - 1 < mail.Attachments.Count; ++i)
                        {
                            Console.WriteLine($@"Saving {mail.Attachments[i].FileName}");
                            //Console.WriteLine(Path.Combine(AttachPath, mail.Attachments[i].FileName));
                            string filepath = Path.Combine(AttachPath, mail.Attachments[i].FileName);
                            mail.Attachments[i].SaveAsFile(filepath);

                            //if (File.Exists(filepath))
                            //{
                            //    mail.Delete(); //after saving the file delete the mail
                            //}
                        }
                    }
                    else
                    {
                        Console.WriteLine("No attachments found: execute auto reply...");
                        Outlook.MailItem replyMail = mail.Reply();
                        replyMail.HTMLBody = $@"Some answer for reply";
                        replyMail.Send();
                    }

                    Console.WriteLine("Delete mail: " + mail.Subject.ToString());
                    mail.UnRead = false; //mark as read
                    mail.Delete();
                }
            }
        }

        protected override void OnStop()
        {
            //nothing
        }
    }

目前,该服务可以作为控制台应用程序和Windows服务执行,因此请不要太在意这是出于调试原因。

2 个答案:

答案 0 :(得分:1)

  

“其他解决方案”仅通过加载项显示,但我想为此使用Windows服务。

Microsoft当前不建议并且不支持从任何无人参与的非交互客户端应用程序或组件(包括ASP,ASP.NET,DCOM和NT Services)自动化Microsoft Office应用程序,因为Office可能表现出不稳定在这种环境中运行Office时的行为和/或死锁。

如果要构建在服务器端上下文中运行的解决方案,则应尝试使用对无人值守执行安全的组件。或者,您应该尝试找到允许至少部分代码在客户端运行的替代方法。如果您从服务器端解决方案中使用Office应用程序,则该应用程序将缺少许多成功运行所需的功能。此外,您将承担整体解决方案稳定性的风险。在Considerations for server-side Automation of Office文章中了解有关此内容的更多信息。

作为一种解决方法,您可以考虑使用基于Outlook的低级API-扩展MAPI或围绕该API的任何包装,例如“兑换”。

如果仅使用Exchange,则可以考虑使用Graph API或EWS,有关详细信息,请参见Start using web services in Exchange

答案 1 :(得分:0)

请在架构方面参考Eugene的回答。但是从使用过滤器提取电子邮件的角度来看,您可以尝试使用此代码。

请尝试查找带有返回Outlook.Table的筛选查询的电子邮件,而不是获取Man。 然后,您可以遍历此表以获取电子邮件。

items = inbox.Items