繁体   English   中英

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

[英]How to save only Excel attachments from outlook in C#?

我必须创建一个程序来保存邮件收件箱中的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服务执行,因此此时请不要太在意,这是出于调试原因。

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

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

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

作为一种解决方法,您可以考虑使用基于Outlook的低级API-扩展MAPI或围绕该API的任何包装程序(如Redemption)。

如果仅使用Exchange,则可以考虑使用Graph API或EWS,请参阅开始使用Exchange中的Web服务以获取更多信息。

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

而不是获取items = inbox.Items ,而是尝试使用过滤器查询查找返回Outlook.Table的电子邮件,然后可以对该表进行迭代以获取电子邮件。

const string PropTag = "http://schemas.microsoft.com/mapi/proptag/";
var filter = "@SQL=" + "\"" + PropTag
         + "0x0037001E" + "\"" + " ci_phrasematch " + "\'" + strFilter + "\'";

Outlook.Table table = inbox.GetTable(filter, Outlook.OlTableContents.olUserItems);

while (!table.EndOfTable)            
{
        Outlook.Row nextRow = table.GetNextRow();
        try
        {
            Outlook.MailItem mi;
            try
            {
                string entryId = nextRow["EntryID"];
                var item = outlookNameSpace.GetItemFromID(entryId);
                mi = (Outlook.MailItem)item;
            }
            catch (InvalidCastException ex)
            {
                Console.WriteLine("Cannot cast mail item, so skipping. Error: {0}", e);                       
                continue;
            } 
            //Extract the attachments here and archive or reply - put your logic here
        }
        catch (Exception e)
        {   
            Console.WriteLine("An error occurred: '{0}'", e);
        }
 }  

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM