Exchange Server 2007 Transport Agent Issue - c#

This is the first time i am working on Exchange Server Development. Below is a simple Transport Agent that i am using, this agent should simply update the email Subjects as shown below in the code.
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Exchange.Data.Transport;
using Microsoft.Exchange.Data.Transport.Smtp;
namespace MyAgents
{
public sealed class MyAgentFactory : SmtpReceiveAgentFactory
{
public override SmtpReceiveAgent CreateAgent(SmtpServer server)
{
return new MyAgent();
}
}
public class MyAgent : SmtpReceiveAgent
{
public MyAgent()
{
this.OnEndOfData += new EndOfDataEventHandler(MyEndOfDataHandler);
}
private void MyEndOfDataHandler(ReceiveMessageEventSource source, EndOfDataEventArgs e)
{
e.MailItem.Message.Subject = "This message passed through my agent: " + e.MailItem.Message.Subject;
}
}
}
Below is the Powershell script i am using to install the Agent.
Net Stop MSExchangeTransport
Install-TransportAgent -Name MyAgent -AssemblyPath EmailLogger.dll -TransportAgentFactory MyAgents.MyAgentFactory
Enable-TransportAgent -Identity MyAgent
Net Start MSExchangeTransport
Agent installed successfully using Exchange Management Shell.
Now when i send/receive emails in exchange, Email subjects are not modified. Emails have their original subjects. I don't know why?
I also performed the steps mentioned in below links to debug the Agent but breakpoints are not being hit by Visual Studio Debugger.
http://www.sf-tools.net/Messaging/tabid/55/EntryId/163/Exchange-2010-Transport-Agent.aspx
Debugging MS Exchange 2007 Transport Agent
http://omarjames.com/blog/index.php/debugging-exchange-transport-agent/
My System Configuration
I am using the Exchange Server 2007 Virtual Machine provided by Microsoft from link below
http://www.microsoft.com/en-pk/download/details.aspx?id=14901
I also installed the Visual Studio 2008 on the VM for debugging.
Please help me in resolving the issue?

Problem Solved. :)
I must use Routing Agent instead of SmtpReceive Agent because only Routing Agents are guaranteed to see all the Emails passing through Exchange Server.
Below is the modified working code, Everything else remains same
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Exchange.Data.Transport;
using Microsoft.Exchange.Data.Transport.Routing;
namespace MyAgents
{
public sealed class MyAgentFactory : RoutingAgentFactory
{
public override RoutingAgent CreateAgent(SmtpServer server)
{
return new MyAgent();
}
}
public class MyAgent : RoutingAgent
{
public MyAgent()
{
this.OnSubmittedMessage += new SubmittedMessageEventHandler(this.MySubmittedMessageHandler);
}
public void MySubmittedMessageHandler(SubmittedMessageEventSource source, QueuedMessageEventArgs e)
{
e.MailItem.Message.Subject = "This message passed through my agent: " + e.MailItem.Message.Subject;
}
}
}

Related

use hangfire as windows service by topshelf (.net core 2.2)

I am trying to use hangfire as windows service by using Topshelf in console app .net core 2.2 . I just want to load hangfire dashboard, not adding any job or anything else.
Program.cs
using System;
using Topshelf;
namespace HangfireAsService
{
class Program
{
static void Main(string[] args)
{
HostFactory.Run(config =>
{
config.Service<Bootstrap>(service =>
{
service.ConstructUsing(s => new Bootstrap());
service.WhenStarted(s => s.Start());
service.WhenStopped(s => s.Stop());
});
config.RunAsLocalSystem();
config.SetDescription("Hangfire as windows Service for DataCrawling Project");
config.SetDisplayName("Hangfire Service Custom");
});
}
}
}
Bootstrap.cs
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Owin.Hosting;
namespace HangfireAsService
{
public class Bootstrap
{
private IDisposable _host;
public void Start()
{
var options = new StartOptions { Port = 8999 };
_host = WebApp.Start<Startup>(options);
Console.WriteLine();
Console.WriteLine("Hangfire has started");
Console.WriteLine("Dashboard is available at http://localhost:8999/hangfire");
Console.WriteLine();
}
public void Stop()
{
_host.Dispose();
}
}
}
Startup.cs
using Hangfire;
using Microsoft.AspNetCore.Builder;
using Owin;
using System;
using System.Collections.Generic;
using System.Text;
namespace HangfireAsService
{
public class Startup
{
public void Configuration(IApplicationBuilder appBuilder)
{
GlobalConfiguration.Configuration
.UseSqlServerStorage("Server=111.111.11.1\\INS2017; Database=Hangfire; user=sa;
password=;");
appBuilder.UseHangfireDashboard();
appBuilder.UseHangfireServer();
}
}
}
As you can see, I created 2 classes for my self-host owin and after reviewing the event viewer I got the error displayed below:
The description for Event ID 0 from source HangfireAsService cannot be
found. Either the component that raises this event is not installed on
your local computer or the installation is corrupted. You can install
or repair the component on the local computer.
If the event originated on another computer, the display information
had to be saved with the event.
The following information was included with the event:
Service cannot be started. System.NullReferenceException: Object
reference not set to an instance of an object. at
Microsoft.Owin.Hosting.Utilities.SettingsLoader.FromConfigImplementation..ctor()
at
Microsoft.Owin.Hosting.Utilities.SettingsLoader.<>c.b__1_0()
at System.Threading.LazyInitializer.EnsureInitializedCore[T](T&
target, Func1 valueFactory) at
Microsoft.Owin.Hosting.Utilities.SettingsLoader.LoadFromConfig(IDictionary2
settings) at
Microsoft.Owin.Hosting.Engine.StartContext..ctor(StartOptions options)
at
Microsoft.Owin.Hosting.Starter.DirectHostingStarter.Start(StartOptions
options) at
Microsoft.Owin.Hosting.Starter.HostingStarter.Start(StartOptions
options) at HangfireAsService.Bootstrap.Start() in
C:\MyWorkSpace\Data
Crawling\dataCrawlingConsole\HangfireAsService\Bootstrap.cs:line 17
at HangfireAsService.Program.<>c.b__0_3(Bootstrap s) in
C:\MyWorkSpace\Data
Crawling\dataCrawlingConsole\HangfireAsService\Program.cs:line 15
at
Topshelf.ServiceConfiguratorExtensions.<>c__DisplayClass2_01.<WhenStarted>b__0(T
service, HostControl control) at
Topshelf.Builders.DelegateServiceBuilder1.DelegateServiceHandle.Start(HostControl
hostControl) at
Topshelf.Runtime.Windows.WindowsServiceHost.OnStart(String[] args)
at System.ServiceProcess.ServiceBase.ServiceQueuedMainCallback(Object
state)
The message resource is present, but the message was not found in the message table.
i used same code inside .net framework instead of .net core and work perfectly.after a test something else i notice this problem because of OWIN happened so after i removed it and use using .net core self-host instead of OWIN everything work perfectly.
below link will help you a lot.
https://medium.com/#tocalai/create-windows-service-using-net-core-console-application-dc2f278bbe42

user interface for selenium with specflow c#

my end goal is to have my boss (not a technical person) use the testing software on her own.(without visual studio or any other 3rd party software) So, i need to build a user interface. here is what one of my scenarios look like. scentially have this scenario run in a console( I can figure out the UI later) or have the HTML report that specflows generates done without visual studio.
I also need the user to pick which scenario runs.
using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI;
using System;
using System.Threading.Tasks;
using TechTalk.SpecFlow;
using static Aflutter3.Element_objects.Element;
using static Aflutter3.Element_objects;
using static Aflutter3.Other_Functions;
using static Aflutter3.Login_Class;
namespace Aflutter3
{
[Binding]
public class SigninSteps
{
[Given(#"I open google chrome")]
public void GivenIOpenGoogleChrome()
{
if (Driver != null)
Console.WriteLine("Opened");
else
Console.WriteLine("Unsuccessfully Opened");
}
[Given(#"I go to aflutter sign in page")]
public void GivenIGoToAflutterSignInPage()
{
if (Go_To_LoginPage() == true)
Console.WriteLine("Website successfully Accessed");
else
Console.WriteLine("Website unsuccessfully Accessed");
}
[Given(#"I enter the username and password")]
public void GivenIEnterTheUsernameAndPassword()
{
Enter_Credentials();
Console.WriteLine("Username and password successfully entered");
}
[When(#"i click sign in")]
public void WhenIClickSignIn()
{
Click_Sign_in();
Console.WriteLine("Login To Aflutter Button Successfully Clicked");
}
[Then(#"I should be in the homepage")]
public void ThenIShouldBeInTheHomepage()
{
if (Check_If_Homepage_Loaded())
Console.WriteLine("Homepage was succesfully loaded");
else
Console.WriteLine("Homepage was unsuccesfully loaded");
}
}
}
Better to create a one file, which will go through the all flow - start tests, generate report, maybe open report. It can be cmd file or power-shell script. When this script is executed, all happens and you boss needs only to check report.

Unable to access SPOOneDriveForBusinessFileActivity REST API call

I'm using Microsoft's o365 REST API Client library (https://github.com/Microsoft/o365rwsclient) and have been able to get many of the API calls to work, but am not having any luck with "SPOOneDriveForBusinessFileActivity". Also, I don't see it advertised in the o365 web service atom feed at https://reports.office365.com/ecp/reportingwebservice/reporting.svc
Here is a description of what the events should return : https://support.office.com/en-gb/article/Understanding-the-User-activity-logs-report-80d0b3b1-1ee3-4777-8c68-6c0dedf1f980
Looking at the source code in https://github.com/Microsoft/o365rwsclient/blob/master/TenantReport/SPOOneDriveForBusinessFileActivity.cs it appears to be a valid function, but when utilizing the o365rwsclient library from a c# application (below) I get a 404 error (URL not found).
Any ideas what's going on? Is this report implemented (Powershell cmdlet or direct REST call would also be acceptable)- and if so, how can I access it?
using Microsoft.Office365.ReportingWebServiceClient;
using System;
namespace O365ReportingDataExport
{
internal class Program
{
private static void Main(string[] args)
{
ReportingContext context = new ReportingContext();
//If you enter invalid authentication information, Visual Studio will throw an exception.
context.UserName = #"PUT YOUR OFFICE 365 USER EMAIL ADDRESS HERE";
context.Password = #"PUT YOUR OFFICE 365 USER PASSWORD HERE";
//FromDateTime & ToDateTime are optional, default value is DateTime.MinValue if not specified
context.FromDateTime = DateTime.MinValue;
context.ToDateTime = DateTime.MinValue;
context.SetLogger(new CustomConsoleLogger());
IReportVisitor visitor = new CustomConsoleReportVisitor();
ReportingStream stream1 = new ReportingStream(context, "SPOOneDriveForBusinessFileActivity", "stream1");
//Calls VisitReport
stream1.RetrieveData(visitor);
Console.WriteLine("Press Any Key...");
Console.ReadKey();
}
private class CustomConsoleLogger : ITraceLogger
{
public void LogError(string message)
{
Console.WriteLine(message);
}
public void LogInformation(string message)
{
Console.WriteLine(message);
}
}
private class CustomConsoleReportVisitor : IReportVisitor
{
public override void VisitBatchReport()
{
foreach (ReportObject report in this.reportObjectList)
{
VisitReport(report);
}
}
public override void VisitReport(ReportObject record)
{
Console.WriteLine("Record: " + record.Date.ToString());
}
}
}
}
After talking to Microsoft's O365 support team, it appears that being able to see file activity in OneDrive for Business is a feature that is still in internal testing (hence being able to see it in their REST API's) that has not been deployed yet.

Testing local project in Visual Studio using selenium web driver

I am trying to set up a visual studio project with acceptance tests using NUnit and Selenium Web Driver, I would like to be able to "run tests" and this to start my web site, use selenium to run the tests and quit.
I have this basic setup so far:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.PhantomJS;
namespace FrontEndTests.AcceptanceTests
{
[TestFixture]
class Phantom
{
private PhantomJSDriver _driver;
[SetUp]
public void WhenOpeningANewWebPage()
{
_driver = new PhantomJSDriver();
_driver.Navigate().GoToUrl(#"localhost");
}
[Test]
public void ThenICanFindAClass()
{
Assert.NotNull(_driver.FindElement(By.ClassName("featured")));
}
[TearDown]
public void Finally()
{
_driver.Quit();
}
}
}
If I set the URL to 'www.google.com' the tests pass fine (with the correct class set) but localhost returns elementnotfoundexception in selenium.
How do I get it to work locally?
Thanks
Based on this:
"When I run the project in visual studio it points to localhost:31106 I have tried to using this as the URL but this gives the same error - Gregg_1987"
IIS must be running your application. When you click run it starts the application in IIS express for the time that the application is running. Visual Studio then attaches to this for execution purposes.
If you are trying to execute Selenium on this you would have to install regular IIS and register the application through IIS so that it will be accessible. Then your tests can hit this through the URL registered in IIS. Otherwise you would have to try to programmatically execute the app using IIS express which there is some guidance on here: Automatically start ASP.MVC project when running test project
Once the site is accessible through IIS you can then hit it with your Selenium tests.
Well, you need to start you site before all tests or you can start it once in SetUp and kill it in TearDown (or if you are going to run your tests on some CI then run once before all tests and kill after all). To start it you can choose either webdev or iisexpress (on your choice), below sample of using WebDev.WebHost.dll
public class Phantom
{
private PhantomJSDriver _driver;
//Move this field to base class if you need to start site before each test
//e.g. you can move setup and teardown to base class, it's all up to you
public DevServer WebDevServer { get; private set; }
[SetUp]
public void WhenOpeningANewWebPage()
{
WebDevServer = new DevServer();
WebDevServer.Start();
_driver = new PhantomJSDriver();
_driver.Navigate().GoToUrl(#"localhost");
}
[Test]
public void ThenICanFindAClass()
{
Assert.NotNull(_driver.FindElement(By.ClassName("featured")));
}
[TearDown]
public void Finally()
{
_driver.Quit();
WebDevServer.Stop();
}
}
public class DevServer
{
private Server _webServer;
public DirectoryInfo SourcePath { get; set; }
public string VirtualPath { get; set; }
public int Port { get; set; }
public DevServer()
{
//Port
Port = Settings.WebDevPort;
//Path to your site folde
SourcePath = Settings.WebDevSourcePath;
//Virt path can be ~
VirtualPath = Settings.WebDevVirtualPath;
}
public void Start()
{
Stop();
try
{
_webServer = new Server(Port, VirtualPath, SourcePath.FullName);
_webServer.Start();
}
catch (Exception e)
{
Trace.TraceError("Process cannot be started." + Environment.NewLine + e);
throw;
}
}
public void Stop()
{
if (_webServer != null)
{
_webServer.Stop();
_webServer = null;
}
}
}

How to create a winform app in visual studio 2010 to host a wcf service

I have a working skeleton WCF service. I want to host it in a winform app with a simple start and stop button.
This is how I host in a console app, easy to change to win app
public Program()
{
Console.WriteLine("This is the SERVER console");
var myUri = new Uri[1];
myUri[0] = new Uri(ConfigurationManager.AppSettings["baseAddress"]);
var timeEntryService = new WCFTimeEntryService();
var host = new ServiceHost(timeEntryService, myUri);
host.Open();
Console.WriteLine("Service Started!");
Console.WriteLine("Click any key to close...");
Console.ReadKey();
host.Close();
}
EDIT
First you need an interface that both client and server will use to communicate.
using System;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Data;
namespace TimeEntryService
{
[ServiceContract]
public interface ITimeEntry
{
[OperationContract]
string Ping();
}
}
Then you create the class that will do the work when a client calls.
using System.ServiceModel;
using System.Data;
namespace TimeEntryService
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class WCFTimeEntryService : ITimeEntry
{
public string Ping()
{
return "Pong";
}
}
}
Then make sure you update your App.config (Use WCF Service Configuration Editor)
In my VS2010 its under Tools -> Service Configuration Editor
(Not sure if you need to do something to get it to show there).
When it runs up, you can use the WCF Test Client to confirm its working.
C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\WcfTestClient.exe

Categories