//
//
// Copyright (C) Microsoft. All rights reserved.
//
//
using Microsoft.WindowsServerSolutions.HostedEmail;
using System;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading;
namespace Contoso.EmailService
{
public class MockEmailService
{
private LogManager logManager = LogManager.SingleInstance;
#region Singleton
private static object singletonLock = new object();
private static MockEmailService singleInstance = null;
public static MockEmailService SingleInstance
{
get
{
if (singleInstance == null)
{
lock (singletonLock)
{
if (singleInstance == null)
{
singleInstance = new MockEmailService();
}
}
}
return singleInstance;
}
}
private MockEmailService()
{
}
#endregion
#region Configuration
private EmailServiceConfiguration config = null;
private EmailServiceConfiguration Configuration
{
get
{
if (config == null)
{
lock (this)
{
if (config == null)
{
string filePath = Constants.ConfigrationFilePath;
if (!File.Exists(filePath))
{
logManager.Log("Cannot find configuration file {0}, just create a configuration file use default settings", filePath);
File.WriteAllText(filePath, Resources.DefaultConfgiuration);
}
var schemaPath = Constants.ConfigurationSchemaPath;
if (!File.Exists(schemaPath))
{
logManager.Log("Cannot find configuration schema file {0}, just create it", schemaPath);
File.WriteAllText(schemaPath, Resources.ConfigurationSchema);
}
config = new EmailServiceConfiguration(filePath);
}
}
}
return config;
}
}
private T SimulateOnlineCall(string operationName, Func func)
{
try
{
logManager.Log("[{0}] starts...", operationName);
int duration = Configuration.GetOperationDuration(operationName);
logManager.Log("operation duration is {0} seconds", duration);
if (duration > 0) Thread.Sleep(duration * 1000);
var exception = Configuration.GetOperationException(operationName);
if (exception != null)
{
logManager.Log("Arbitary Exception thrown");
throw exception;
}
var retVal = func();
logManager.Log("[{0}] is done", operationName);
return retVal;
}
catch (Exception e)
{
logManager.Log("ERROR: {0}", e.ToString());
throw;
}
}
private void SimulateOnlineCall(string operationName, Action action)
{
SimulateOnlineCall(operationName, () => { action(); return true; });
}
#endregion
#region Admin Account Management
public bool VerifyAdminAccount(string admin, string password)
{
return SimulateOnlineCall(MethodBase.GetCurrentMethod().Name, () =>
{
// verify the admin account here
if (string.IsNullOrEmpty(admin) || string.IsNullOrEmpty(password))
{
logManager.Log("Administrator account is not valid.");
return false;
}
logManager.Log("Administrator account verified.");
return true;
});
}
public bool Logon(string admin, string password)
{
return SimulateOnlineCall(MethodBase.GetCurrentMethod().Name, () =>
{
// verify the admin account here
if (string.IsNullOrEmpty(admin) || string.IsNullOrEmpty(password))
{
logManager.Log("Administrator account is not valid.");
return false;
}
logManager.Log("Administrator account verified.");
return true;
});
}
public void LogOff(string admin)
{
SimulateOnlineCall(MethodBase.GetCurrentMethod().Name, () =>
{
if (string.IsNullOrEmpty(admin)) return;
logManager.Log("{0} logged off", admin);
});
}
#endregion
#region Email address validation
// Please replace the following regex in a real case
private static readonly Regex emailAddressPattern = new Regex(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
public void ValidateEmailAddress(string email)
{
// email domain might be checked as well but this is bypassed in this example
if (string.IsNullOrWhiteSpace(email) || !emailAddressPattern.Match(email).Success)
{
throw new HostedEmailAdaptorException(HostedEmailAdaptorErrorCode.InvalidEmailAddress, null);
}
}
#endregion
#region Email Account Management
private AccountManager accountManager = new AccountManager(Constants.AccountDataFilePath);
public bool ContainsAccount(string accountId)
{
return SimulateOnlineCall(MethodBase.GetCurrentMethod().Name, () =>
{
return accountManager.ContainsAccount(accountId);
});
}
public bool ContainsPrimaryEmailAddress(string emailAddress)
{
return SimulateOnlineCall(MethodBase.GetCurrentMethod().Name, () =>
{
return accountManager.ContainsPrimaryEmailAddress(emailAddress);
});
}
public EmailAccountInfo AddAccount(EmailAccountInfo info)
{
if (info == null) throw new ArgumentNullException("info");
return SimulateOnlineCall(MethodBase.GetCurrentMethod().Name, () =>
{
ValidateEmailAddress(info.PrimaryEmailAddress);
if (info.AdditionalEmailAddresses != null)
{
foreach (string emailAddress in info.AdditionalEmailAddresses)
{
ValidateEmailAddress(emailAddress);
}
}
return accountManager.AddAccount(info);
});
}
public void UpdateAccount(EmailAccountInfo info)
{
if (info == null) throw new ArgumentNullException("info");
if (info.PrimaryEmailAddress != null)
{
ValidateEmailAddress(info.PrimaryEmailAddress);
}
SimulateOnlineCall(MethodBase.GetCurrentMethod().Name, () =>
{
var original = accountManager.GetAccountById(info.AccountId);
if (original == null) throw new AccountNotExistsException();
EmailAccountInfo updated = null;
if (info.ExtendedProperties == null)
{// No extended properties to update, just copy the changed properties to original one
if (info.PrimaryEmailAddress != null) original.PrimaryEmailAddress = info.PrimaryEmailAddress;
if (info.DisplayName != null) original.DisplayName = info.DisplayName;
if (info.FirstName != null) original.FirstName = info.FirstName;
if (info.LastName != null) original.LastName = info.LastName;
updated = original;
}
else
{// There is some extended properties to update, copy original properties to non-changed ones
if (info.PrimaryEmailAddress == null) info.PrimaryEmailAddress = original.PrimaryEmailAddress;
if (info.DisplayName == null) info.DisplayName = original.DisplayName;
if (info.FirstName == null) info.FirstName = original.FirstName;
if (info.LastName == null) info.LastName = original.LastName;
if (original.ExtendedProperties != null)
{
foreach (var pair in original.ExtendedProperties)
{
if (!info.ExtendedProperties.ContainsKey(pair.Key)) info.ExtendedProperties.Add(pair.Key, pair.Value);
}
}
// this should not be changed by this method, there are specific methods for enable/disable
info.Enabled = original.Enabled;
updated = info;
}
ValidateEmailAddress(info.PrimaryEmailAddress);
if (info.AdditionalEmailAddresses != null)
{
foreach (string emailAddress in info.AdditionalEmailAddresses)
{
ValidateEmailAddress(emailAddress);
}
}
accountManager.UpdateAccount(info);
});
}
public EmailAccountInfo GetAccountById(string accountId)
{
return SimulateOnlineCall(MethodBase.GetCurrentMethod().Name, () =>
{
return accountManager.GetAccountById(accountId);
});
}
public EmailAccountInfo GetAccountByPrimaryEmail(string emailAddress)
{
return SimulateOnlineCall(MethodBase.GetCurrentMethod().Name, () =>
{
return accountManager.GetAccountByPrimaryEmail(emailAddress);
});
}
public void RemoveAccount(string accountId)
{
SimulateOnlineCall(MethodBase.GetCurrentMethod().Name, () =>
{
accountManager.RemoveAccount(accountId);
});
}
public void EnableAccount(string accountId)
{
SimulateOnlineCall(MethodBase.GetCurrentMethod().Name, () =>
{
accountManager.EnableAccount(accountId);
});
}
public void DisableAccount(string accountId)
{
SimulateOnlineCall(MethodBase.GetCurrentMethod().Name, () =>
{
accountManager.DisableAccount(accountId);
});
}
public EmailAccountInfo[] GetAllAccounts()
{
return SimulateOnlineCall(MethodBase.GetCurrentMethod().Name, () =>
{
return accountManager.GetAllAccounts();
});
}
public void ResetPassword(string accountId, string password)
{
SimulateOnlineCall(MethodBase.GetCurrentMethod().Name, () => { });
}
#endregion
public string[] GetDomains()
{
return SimulateOnlineCall(MethodBase.GetCurrentMethod().Name, () =>
{
//return (string[])null;
return new string[]{"contoso.com", "contosocontoso.com", "contosocontoso1.com"};
});
}
#region Extended features
public DistributionGroup[] GetDistributionGroups()
{
return Configuration.DistributionGroups;
}
#endregion
}
}