Introduction
This article talks about the tips/tricks involved while integrating email services in your web application using Enterprise Web Services(EWS). If you are planning to host your application in Azure by implementing your organizations email configurations, then this is one of the best approaches. There is an agile nature of maintaining these kind of practices in a hosted Azure solution.For example, your enterprise uses Office 2007 exchange server and because of their recent migrations to exchange server 2013 with an Office 365 implementation, their application configurations may not work. In this scenario, with a new service URL reference and a small change in your email sending source code can start your email services in Azure environment.
Background
In your legacy .NET web applications, you might have used different kind of email libraries for sending emails. This works really great when you are building an on premise web application where hosting need is maintained on premise datacenter. Enterprises were using Office exchange server 2007, 2007 sp1, 2010 exchange server, etc, but when the cloud scenario came to the market, giants like Google, Microsoft put their brains into this business and made some great frameworks to maintain all your Office stuff in a single place where you can access them from your IPad, Mobile. Within your enterprise firewall boundary. Google named them Google drive with minimal features but, when Microsoft came to this space, they have introduced the same concept like Google did in Google Drive but with better Office management. Organizations that are using exchange server 2007 or 2010 are more likely to love this way of Office representation. They have started migrating their office apps to Office 365. This kind of strategy hurt our developers a lot because when a traditional web application is shipped to Windows Azure, then the developer has to do some research to migrate everything to Windows Azure. Again, when the small mind (Developer) came to know that Office 365 integrations are up and running in enterprise, they started biting their nails.
Some folk saints came to their dream and told them they heard about Microsoft exchange web services which can solve their issue. Developer ran to his workplace with this idea and started R&D on Exchange web services and he/she has found that this can help them to run Office 365/any exchange email services in Azure. He explored the below code snippets.
Using the Code
To use Microsoft exchange web services, please add a service reference. You have to add the WSDL URL to configure the web service.
Your Office 365 URL will look like below:
https://podsomedigits.outlook.com/EWS/Services.wsdl
The bold one will be a unique tenant id.
Once you add the web services, click on the property of added service reference and make the url behavior ‘Dynamic’.
Now write a reusable class which can be used for sending emails.
In the below Email Manager Class abcd stands for namespace.
Now your Exchange configurations in Web.config shall be listed as below:
<add key="FromEmail" value="cpadmin@codeproject.com" />
<add key="EchangeUser" value="cpadmin@codeproject.com" />
<add key="ExchangePassword" value="password123" />
<add key="ExchangeDomain" value="cfi" />
<add key="ExchangeServiceUrl" value="https://podsomedigits.outlook.com/EWS/Exchange.asmx" />
Please don’t copy paste. The above configurations value is for your understanding.
esb.RequestServerVersionValue.Version = ExchangeVersionType.Exchange2013_SP1;
The above line is really agile. Now in future if Microsoft comes with Exchange2014, then once you reconfigure your web reference, you can get the required exchange version type. If your enterprise will degrade exchange server, then also you can change this type. Degradation never happens!
Email Manager Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Configuration;
using abcd.DTO;
using abcd.ExchangeWebServices;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
namespace abcd
{
public static class EmailManager
{
public static string SendMail(EmailDTO emailContent)
{ string returnMsg = string.Empty;
string userName = ConfigurationManager.AppSettings["EchangeUser"].ToString();
string password = ConfigurationManager.AppSettings["ExchangePassword"].ToString();
string domain = ConfigurationManager.AppSettings["ExchangeDomain"].ToString();
string serviceUrl = ConfigurationManager.AppSettings["ExchangeServiceUrl"].ToString();
string fromEmail = ConfigurationManager.AppSettings["FromEmail"].ToString();
ServicePointManager.ServerCertificateValidationCallback =
delegate(Object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{
return true;
};
ExchangeServiceBinding esb = new ExchangeServiceBinding();
esb.Credentials = new NetworkCredential(userName, password, domain);
esb.Url = serviceUrl;
esb.RequestServerVersionValue = new RequestServerVersion();
esb.RequestServerVersionValue.Version = ExchangeVersionType.Exchange2013_SP1;
CreateItemType createEmailRequest = new CreateItemType();
createEmailRequest.MessageDisposition = MessageDispositionType.SendAndSaveCopy;
createEmailRequest.MessageDispositionSpecified = true;
createEmailRequest.SavedItemFolderId = new TargetFolderIdType();
DistinguishedFolderIdType sentitems = new DistinguishedFolderIdType();
sentitems.Id = DistinguishedFolderIdNameType.sentitems;
createEmailRequest.SavedItemFolderId.Item = sentitems;
createEmailRequest.Items = new NonEmptyArrayOfAllItemsType();
MessageType message = new MessageType();
message.Subject = emailContent.Subject;
message.Body = new BodyType();
message.Body.BodyType1 = BodyTypeType.HTML;
message.Body.Value =
emailContent.Body;
message.Sender = new SingleRecipientType();
message.Sender.Item = new EmailAddressType();
message.Sender.Item.EmailAddress = fromEmail;
if (emailContent.ToRecipientsEmail != null)
{
message.ToRecipients = new EmailAddressType[emailContent.ToRecipientsEmail.Count];
for (int index = 0; index < emailContent.ToRecipientsEmail.Count; index++)
{
message.ToRecipients[index] = new EmailAddressType();
message.ToRecipients[index].EmailAddress = emailContent.ToRecipientsEmail[index];
}
}
if (emailContent.CcRecipientsEmail != null)
{
message.CcRecipients = new EmailAddressType[emailContent.CcRecipientsEmail.Count];
for (int index = 0; index < emailContent.CcRecipientsEmail.Count; index++)
{
message.CcRecipients[index] = new EmailAddressType();
message.CcRecipients[index].EmailAddress = emailContent.CcRecipientsEmail[index];
}
}
if (emailContent.BccRecipientsEmail != null)
{
message.BccRecipients = new EmailAddressType[emailContent.BccRecipientsEmail.Count];
for (int index = 0; index < emailContent.BccRecipientsEmail.Count; index++)
{
message.BccRecipients[index] = new EmailAddressType();
message.BccRecipients[index].EmailAddress = emailContent.BccRecipientsEmail[index];
}
}
message.Sensitivity = SensitivityChoicesType.Normal;
createEmailRequest.Items.Items = new ItemType[1];
createEmailRequest.Items.Items[0] = message;
CreateItemResponseType createItemResponse = esb.CreateItem(createEmailRequest);
ArrayOfResponseMessagesType responses = createItemResponse.ResponseMessages;
ResponseMessageType[] responseMessages = responses.Items;
foreach (ResponseMessageType respMsg in responseMessages)
{
if (respMsg.ResponseClass == ResponseClassType.Error)
{
returnMsg = "Error: " + respMsg.MessageText;
return returnMsg;
}
else if (respMsg.ResponseClass == ResponseClassType.Warning)
{
returnMsg = "Warning: " + respMsg.MessageText;
return returnMsg;
}
}
returnMsg = "Mail Sent Successfully";
return returnMsg;
}
private static bool CertificateValidationCallBack(object sender,
System.Security.Cryptography.X509Certificates.X509Certificate certificate,
System.Security.Cryptography.X509Certificates.X509Chain chain,
System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
{
return true;
}
if ((sslPolicyErrors & System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors) != 0)
{
if (chain != null && chain.ChainStatus != null)
{
foreach (System.Security.Cryptography.X509Certificates.X509ChainStatus status in chain.ChainStatus)
{
if ((certificate.Subject == certificate.Issuer) &&
(status.Status == System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.UntrustedRoot))
{
continue;
}
else
{
if (status.Status != System.Security.Cryptography.X509Certificates.X509ChainStatusFlags.NoError)
{
return false;
}
}
}
}
return true;
}
else
{
return false;
}
}
}
}
DTO Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace abcd.DTO
{
public class EmailDTO
{
public virtual string Subject { get; set; }
public virtual string Body { get; set; }
public virtual List<string> ToRecipientsEmail { get; set; }
public virtual List<string> CcRecipientsEmail { get; set; }
public virtual List<string> BccRecipientsEmail { get; set; }
}
}
Calling Time
EmailDTO objEmail = new EmailDTO();
objEmail.ToRecipientsEmail = from your To textbox;
objEmail.CcRecipientsEmail = From your CC textbox;
objEmail.BccRecipientsEmail = From your BCC textbox;
objEmail.Subject = subject;
objEmail.Body = body;
string retMsg = EmailManager.SendMail(objEmail);
if (retMsg.ToUpper().Contains("ERROR") ||
(retMsg.ToUpper().Contains("WARNING")))
{
Logging.LogError(retMsg);
ShowMessage(retMsg, "message_error");
}
else
{
ShowMessage(retMsg, "message_success");
}
Apart from this mail functionality, you can consume lots of other Office 365 services from this exchange web services.
Points of Interest
This kind of source code for using email services really helped us because when our client changed the exchange server from 2007 to 2013, it was helpful for us to maintain the services by changing a single line of code.
esb.RequestServerVersionValue.Version = ExchangeVersionType.Exchange2007_SP1;
to:
esb.RequestServerVersionValue.Version = ExchangeVersionType.Exchange2013_SP1;
References
- http://msdn.microsoft.com/en-us/library/office/bb408521%28v=exchg.140%29.aspx
- http://msdn.microsoft.com/en-us/library/office/dd633677%28v=exchg.80%29.aspx
- http://msdn.microsoft.com/en-us/library/office/aa563009%28v=exchg.140%29.aspx
History
- 24th May, 2016: Initial version