0

所以我一直在研究一种在 FOPE 上自动搜索的方法。令人讨厌的是,Microsoft 没有提供 API 来访问它收集的数据,因此我必须模拟一个具有登录、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 显示它正在工作后,结果会填充到页面中。

我已经通过 C# 以编程方式查看了将用户名和密码发布到登录页面以及登录到网站,但这两种解决方案似乎都不起作用。我希望那里的一些 FOPE 管理员可以帮助我弄清楚发生了什么以及如何进行这项工作。如果您需要我尝试一些东西或提供更多信息,请告诉我。

更新#1

所以我在这方面取得了一些进展。XAML 端并没有什么特别之处(只是一个带有 URL 空间的文本框、一个开始搜索的按钮和一个 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") 部分时,我被卡住了。似乎出现以下错误:

>未知模块中发生“Microsoft.CSharp.RuntimeBinder.RuntimeBinderException”类型的异常。但未在用户代码中处理

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

如果有这个异常的处理程序,程序可以安全地继续。

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

更新#2

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

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

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

4

1 回答 1

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;
        }
    }
}
}
于 2012-12-07T21:49:48.597 回答