所以我一直致力于自动搜索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管理员可以帮我弄清楚最新情况以及如何使这项工作。如果您需要我尝试或提供更多信息,请告诉我。
所以我在这方面取得了一些进展。 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中,但实际上它仍然没有提交表单。有没有人有任何建议?
似乎我坐在答案上一直提交表格。应该谨慎使用动态的另一个原因,因为您将无法获得任何IntelliSense帮助。我所做的只是提交表格:
doc.GetElementById("submit_signin").Click();
现在我只需要研究如何从搜索中获取结果(仅在JavaScript中),并确定在提交表单后加载的页面何时完成加载。
答案 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;
}
}
}
}