How to: Implement Basic Email Functionality
Applies To: Windows Server 2012 Essentials
In order to support the basic functionality required of all hosted email adapters, you must implement a class that supports the IHostedEmailAdaptor interface. Your class must connect to your hosting service and be able to invoke the basic management operations. The built-in provider calls your class through the interface in order to manage all of the associated hosted email accounts. Note that this interface is a management interface, rather than one that passes the actual emails.
The general purpose of a IHostedEmailAdaptor implementation is to pass the requests from the provider (from the user or administrator) to the hosted email service. Therefore, most implementations of IHostedEmailAdaptor will likely deal primarily with sockets, crossing LAN/WAN boundaries, and other communications issues. Due to the importance of email in a business environment, it is recommended that you should use a secure communications channel in your implementation. Also, most of the processing and decision making will likely be done by the service, rather than the adapter. However, as necessary, you can implement basic business logic in your adapter to support your solution.
The following list describes the functions that you must support:
Required Member | Description |
---|---|
Connected | Describes whether the adapter is connected to the hosted email service. |
Activate | Initializes the adapter. |
Connect | Connects to the hosted email management service. |
CreateAccount | Creates a new user account. |
Deactivate | Disables the adapter. |
DeleteAccount | Deletes an existing account. |
GetAccount | Retrieves information about a specified account. |
GetAllAccounts | Retrieves a collection of all accounts. |
ResetAdminCredential | Resets the admin credentials. |
UpdateAccount | Updates the specified email account. |
You do not need to implement all of the functions defined in the adapter interface. The following table describes the optional IHostedEmailAdaptor members. Note that while these members are optional, many contain useful functionality that the framework can automatically call and add to the user experience. Therefore, it is recommended that you implement as many these functions as possible.
Optional Member | Description |
---|---|
DisableAccount | Disables an active email account. |
EnableAccount | Enables a disabled email account. |
GetDomains | Retrieves the email domains associated with the hosted email service. |
ResetPassword | Resets the password on the specified email account. |
If you decide not to support an optional function, you should mark the function with [NotSupportedAPI]
attribute in your adapter class.
Tip
When implementing the adapter, you should use HostedEmailAdaptorException to throw errors to the built-in provider. For more information, see How to: Implement Adapter Error Handling.
Example
The following class implements IHostedEmailAdaptor. Note that most of these implementations make local calls to the EmailService
class, rather than going out to a hosted email service. This is because the code is from the SDK sample, which is designed to run on a single installation. For more information, see Quickstart: Creating a Hosted Email Adapter.
using System.Collections.Generic;
using Contoso.EmailService;
using Microsoft.WindowsServerSolutions.Administration.ObjectModel.Adorners;
using Microsoft.WindowsServerSolutions.HostedEmail;
namespace Contoso.HostedEmail.Adaptor
{
public class ContosoHostedEmailAdaptor : IHostedEmailAdaptor
{
#region
private MockEmailService EmailService
{
get
{
return MockEmailService.SingleInstance;
}
}
private LogManager logManager = LogManager.SingleInstance;
public ContosoHostedEmailAdaptor()
{
}
private bool IsActivated
{
get
{
return !string.IsNullOrEmpty(CredentialManager.AdminUserName) && !string.IsNullOrEmpty(CredentialManager.AdminPassword);
}
}
#endregion
#region IHostedEmailAdaptor
public void Activate(string admin, string password, IDictionary<string, string> extendedParameters)
{
lock (this)
{
if (IsActivated)
{
logManager.Log("Already activated");
throw new HostedEmailAdaptorException(HostedEmailAdaptorErrorCode.Custom, new AddinErrorRecord()
{
ErrorCode = 0,
Message = Resources.ErrMsg_AlreadyActivated,
Title = Resources.ErrTitle_AlreadyActivated,
});
}
logManager.Log("admin: {0}, password should not be logged", admin);
if (!EmailService.VerifyAdminAccount(admin, password))
{
throw new HostedEmailAdaptorException(HostedEmailAdaptorErrorCode.AuthenticationFailure, null);
}
CredentialManager.ClearAll();
CredentialManager.AdminUserName = admin;
CredentialManager.AdminPassword = password;
}
}
public void Deactivate(IDictionary<string, string> extendedParameters)
{
lock (this)
{
CredentialManager.ClearAll();
}
}
private bool connected = false;
public void Connect()
{
if (!IsActivated)
{
connected = false;
}
connected = EmailService.Logon(CredentialManager.AdminUserName, CredentialManager.AdminPassword);
}
public void Disconnect()
{
EmailService.LogOff(CredentialManager.AdminUserName);
connected = false;
}
public bool Connected
{
get
{
return connected;
}
}
public void ResetAdminCredential(string admin, string password, IDictionary<string, string> extendedParameters)
{
if (!EmailService.VerifyAdminAccount(admin, password))
{
throw new HostedEmailAdaptorException(HostedEmailAdaptorErrorCode.AuthenticationFailure, null);
}
logManager.Log("ResetAdminCredential to admin: {0}", admin);
CredentialManager.AdminUserName = admin;
CredentialManager.AdminPassword = password;
}
public EmailAccountInfo CreateAccount(EmailAccountInfo info, string password)
{
try
{
return EmailService.AddAccount(info);
}
catch (AccountExistsException)
{
throw new HostedEmailAdaptorException(HostedEmailAdaptorErrorCode.AccountAlreadyExists, new AddinErrorRecord()
{
Message = Resources.ErrMsg_OnlineUserAlreadyExist,
Title = Resources.ErrTitle_OnlineUserAlreadyExist,
});
}
}
public void DeleteAccount(string accountId)
{
try
{
EmailService.RemoveAccount(accountId);
}
catch (AccountNotExistsException)
{
throw new HostedEmailAdaptorException(HostedEmailAdaptorErrorCode.AccountNotExists, new AddinErrorRecord()
{
Message = Resources.ErrMsg_OnlineUserNotExist,
Title = Resources.ErrTitle_OnlineUserNotExist,
});
}
}
public void DisableAccount(string accountId)
{
try
{
EmailService.DisableAccount(accountId);
}
catch (AccountNotExistsException)
{
throw new HostedEmailAdaptorException(HostedEmailAdaptorErrorCode.AccountNotExists, new AddinErrorRecord()
{
Message = Resources.ErrMsg_OnlineUserNotExist,
Title = Resources.ErrTitle_OnlineUserNotExist,
});
}
}
public void EnableAccount(string accountId)
{
try
{
EmailService.EnableAccount(accountId);
}
catch (AccountNotExistsException)
{
throw new HostedEmailAdaptorException(HostedEmailAdaptorErrorCode.AccountNotExists, new AddinErrorRecord()
{
Message = Resources.ErrMsg_OnlineUserNotExist,
Title = Resources.ErrTitle_OnlineUserNotExist,
});
}
}
public EmailAccountInfo GetAccount(string accountId)
{
try
{
return EmailService.GetAccountById(accountId);
}
catch (AccountNotExistsException)
{
throw new HostedEmailAdaptorException(HostedEmailAdaptorErrorCode.AccountNotExists, new AddinErrorRecord()
{
Message = Resources.ErrMsg_OnlineUserNotExist,
Title = Resources.ErrTitle_OnlineUserNotExist,
});
}
}
public EmailAccountInfo[] GetAllAccounts()
{
return EmailService.GetAllAccounts();
}
public string[] GetDomains()
{
return EmailService.GetDomains();
}
public void ResetPassword(string accountId, string password)
{
try
{
EmailService.GetAccountById(accountId);
EmailService.ResetPassword(accountId, password);
}
catch (AccountNotExistsException)
{
throw new HostedEmailAdaptorException(HostedEmailAdaptorErrorCode.AccountNotExists, new AddinErrorRecord()
{
Message = Resources.ErrMsg_OnlineUserNotExist,
Title = Resources.ErrTitle_OnlineUserNotExist,
});
}
}
public void UpdateAccount(EmailAccountInfo info)
{
try
{
EmailService.UpdateAccount(info);
}
catch (AccountNotExistsException)
{
throw new HostedEmailAdaptorException(HostedEmailAdaptorErrorCode.AccountNotExists, null);
}
catch (AccountExistsException)
{
throw new HostedEmailAdaptorException(HostedEmailAdaptorErrorCode.AccountAlreadyExists, null);
}
catch (InvalidEmailAddressException)
{
throw new HostedEmailAdaptorException(HostedEmailAdaptorErrorCode.InvalidEmailAddress, null);
}
}
#endregion
}
}