自动执行Microsoft FOPE(Forefront Online Protection for Exchange)搜索

时间:2012-10-31 18:34:44

标签: c# exchange-server

所以我一直致力于自动搜索FOPE。微软烦人地不提供API来访问它收集的数据,因此我必须模拟一个web浏览器,其中包含登录,cookie,报废页面的所有怪癖,然后使用该数据进一步刮掉某些链接。我应该能够获得的最后几个部分,但MS用于FOPE的设置让我感到困惑。我会发布我所知道的和我所拥有的内容,所以希望其他一些管理员或程序员可以提供帮助。也许这里的信息可以帮助其他管理员解决这个问题,因为看起来MS实际上并不想让用户友好。

https://sts.messaging.microsoft.com/login.asp

<form name="signin" method="post" id="signin" action="">
<span class="normal">Sign in:</span>                 
<fieldset>
    <label for="email">User name:</label>
    <input type="text" id="email" name="email" maxlength="384" value="" /><br />
    <label for="Password">Password:</label>
    <input type="password" id="Password" name="Password" maxlength="256" /><br />
    <input type="submit" id="submit_signin" name="SignIn" value="Sign in" />
</fieldset>
</form>

登录后,我需要https://admin.messaging.microsoft.com/Home.mvc/(经过几次自动重定向后)。在这里,我点击工具按钮,它将我带到搜索页面。

https://admin.messaging.microsoft.com/TraceMessage.mvc/Index/123456

<fieldset>
    <div class="legend">
        <h3><span>Search Parameters</span></h3>
    </div>
    <ul class="fieldset">
        <li class="row large">
            <div class="field"><div class="shell">
    <label for="Sender">* Sender address:</label>
    <span class="input"><span><input type="text" id="Sender" name="Sender" value="" /></span></span>
            </div></div>
            <div class="field last"><div class="shell">
    <label for="Recipient">* Recipient address:</label>
    <span class="input"><span><input type="text" id="Recipient" name="Recipient" value="" /></span></span>
            </div></div>
        </li>
        <li class="row large">
            <div class="field"><div class="shell">
    <label for="Start">* Start date:</label>
    <span class="input"><span><input type="text" id="Start" name="Start" value="10/29/2012 1:19:20 PM"/></span></span>
            </div></div>
            <div class="field last"><div class="shell">
    <label for="End">* End date:</label>
    <span class="input"><span><input type="text" id="End" name="End" value="10/31/2012 1:19:20 PM"/></span></span>
            </div></div>
        </li>
        <li class="row large">
            <div class="field"><div class="shell">
    <label for="Adjust">Time zone:</label>
    <div class="input select">
        <select id="Adjust" name="Adjust">
            <option value="-5"  selected="selected"  >
                UTC-5</option>
        </select>
            </div></div></div>
            <div class="field last"><div class="shell">
    <label for="MessageId">Message ID:</label>
    <span class="input"><span><input type="text" id="MessageId" name="MessageId" value=""/></span></span>
            </div></div>
        </li>
    </ul>
    <br />* Fields marked with the star are required.
</fieldset>
<div>
    <span class="buttons">
        <input type="submit" id="submit" value="Search" />
    </span>
</div>

在此页面上,我需要插入发件人(user@exampleSender.com)和收件人域(exampleReceiver.com)。在使用一些JS显示它正在工作之后,结果会在页面中填充。

我已经看过Post Username and Password to login page programmatically以及Login to website, via C#,但两种解决方案似乎都不起作用。我希望那里的一些FOPE管理员可以帮我弄清楚最新情况以及如何使这项工作。如果您需要我尝试或提供更多信息,请告诉我。

更新#1

所以我在这方面取得了一些进展。 XAML方面并不特别(只有一个带空格的文本框,一个开始搜索的按钮,以及一个WPF WebBrowser。

    private void executeButton_Click(object sender, RoutedEventArgs e)
    {
        DateTime timeNow = DateTime.Now;
        TimeZone zone = TimeZone.CurrentTimeZone;
        TimeSpan offset = zone.GetUtcOffset(DateTime.Now);

        this.wbControl.Navigate("https://admin.messaging.microsoft.com/TraceMessage.mvc/Trace/123456?s=" + Uri.EscapeUriString(this.inputTB.Text) + "&r=example.com&d=" + Uri.EscapeUriString(timeNow.AddDays(-29).ToString()) + "&e=" + Uri.EscapeUriString(timeNow.ToString()) + "&a=" + Uri.EscapeUriString(offset.Hours.ToString()));
   }

    private void wbControl_LoadCompleted_1(object sender, NavigationEventArgs e)
    {
        string email = "AUSERNAME";
        string password = "APASSWORD";

        dynamic doc = this.wbControl.Document;

        doc.GetElementById("email").SetAttribute("value", email);
        doc.GetElementById("Password").SetAttribute("value", password);
        doc.GetElementById("submit_signin").InvokeMember("click");
    }

由于目前这是用于测试功能,因此某些方面是硬编码的(用户名和密码),最终不会这样。此时,我遇到了代码的InvokeMember(“click”)部分。以下内容似乎有误:

  

&gt;未知模块中出现“Microsoft.CSharp.RuntimeBinder.RuntimeBinderException”类型的例外情况。但未在用户代码中处理

     

其他信息:'System.MarshalByRefObject.InvokeMember(string,&gt; System.Reflection.BindingFlags,System.Reflection.Binder,object [],&gt; System.Reflection.ParameterModifier [],System.Globalization.CultureInfo,string [])'由于其保护级别而无法访问

     

如果存在此异常的处理程序,则可以安全地继续该程序。

所以我把它包装在一个空白的try / catch中,但实际上它仍然没有提交表单。有没有人有任何建议?

更新#2

似乎我坐在答案上一直提交表格。应该谨慎使用动态的另一个原因,因为您将无法获得任何IntelliSense帮助。我所做的只是提交表格:

doc.GetElementById("submit_signin").Click();

现在我只需要研究如何从搜索中获取结果(仅在JavaScript中),并确定在提交表单后加载的页面何时完成加载。

1 个答案:

答案 0 :(得分:0)

好的,经过多次战斗后我得到了解决方案。如果有人需要复制它/改进它,我会发布.cs代码。截至目前,它的效果非常好:

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections;
using HtmlAgilityPack;
using System.Data;

namespace TestApp
{
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void executeButton_Click(object sender, RoutedEventArgs e)
    {
        DateTime timeNow = DateTime.Now;
        TimeZone zone = TimeZone.CurrentTimeZone;
        TimeSpan offset = zone.GetUtcOffset(DateTime.Now);

        string email = "USERNAME";
        string password = "PASSWORD";

        List<string> URLList = new List<string>();

        foreach (string domain in Domains)
        {
            URLList.Add("https://admin.messaging.microsoft.com/TraceMessage.mvc/AsyncMessageList/123456?s=" + Uri.EscapeUriString(this.inputTB.Text) + "&r=" + domain + "&d=" + Uri.EscapeUriString(timeNow.AddDays(-29).ToString()) + "&e=" + Uri.EscapeUriString(timeNow.ToString()) + "&a=" + Uri.EscapeUriString(offset.Hours.ToString()));
        }

        var domainQueue = new Queue<string>(URLList);

        Action navigateQueue = () =>
        {
            if (domainQueue.Count != 0)
            {
                this.wbControl.Navigate(domainQueue.Dequeue());
            }
            else
            {
                MessageBox.Show("Completed");
            }
        };

        this.wbControl.LoadCompleted += (o, e0) =>
        {
            if (this.wbControl.IsLoaded == true)
            {
                dynamic doc = this.wbControl.Document;

                try
                {
                    doc.GetElementById("email").SetAttribute("value", email);
                    doc.GetElementById("Password").SetAttribute("value", password);
                    doc.GetElementById("submit_signin").Click();
                }
                catch
                {
                }

                if (e0.Uri.AbsolutePath.Contains("AsyncMessageList"))
                {
                    List<string> DetailsList = new List<string>();
                    DetailsList.AddRange(ExtractAllAHrefTags(doc));

                    foreach (string href in DetailsList)
                    {
                        domainQueue.Enqueue(href);
                    }
                    navigateQueue();
                }

                if (e0.Uri.AbsolutePath.Contains("Details"))
                {
                    resultsTB.Text += ParseEntries(doc);
                    navigateQueue();
                }

            }
        };

        navigateQueue();
    }

    private string ParseEntries(dynamic inputDoc)
    {
        HtmlAgilityPack.HtmlDocument docHAP = new HtmlAgilityPack.HtmlDocument();
        docHAP.LoadHtml(inputDoc.Body.InnerHtml.ToString());

        string csv = "";

        foreach (HtmlNode emNode in docHAP.DocumentNode.SelectNodes("//em"))
        {
            if (emNode.Attributes["class"] == null)
            {
                csv += "\"" + emNode.InnerText.ToString() + "\",";
            }
        }
        csv = csv.Remove(csv.Length - 1, 1) + "\"" + Environment.NewLine;
        return csv;
    }

    private List<string> ExtractAllAHrefTags(dynamic inputDoc)
    {
        HtmlAgilityPack.HtmlDocument docHAP = new HtmlAgilityPack.HtmlDocument();
        docHAP.LoadHtml(inputDoc.Body.InnerHtml.ToString());

        List<string> hrefTags = new List<string>();
        try
        {
            foreach (HtmlNode link in docHAP.DocumentNode.SelectNodes("//a[@href]"))
            {
                HtmlAttribute att = link.Attributes["href"];
                hrefTags.Add("https://" + this.wbControl.Source.Host.ToString() + System.Web.HttpUtility.HtmlDecode(att.Value));
            }
        }
        catch
        {
        }

        return hrefTags;
    }

    private List<string> Domains
    {
        get
        {
            List<string> currentDomains = new List<string>();
            currentDomains.Add("example.com");
            currentDomains.Add("sub.example.com");
            currentDomains.Add("it.example.com");
            return currentDomains;
        }
    }
}
}