Kalaimaan

Doing simple things to make great life

Send Email using Exchange web service

Posted by kalaimaan on February 9, 2009

Using exchange stub we can send mail to the selected user. In the previous post i have explained how to confiugre Ms Exchange server and creation of  SOAP stub for java.

Here is the sample to send mail to the use. The need two basic file for SSL

1. EWSSSLSocketFactory.java

2. EWSTrustManager.java

and the third one is the sample file for sending mail

3. EWSSendEmail.java

File : EWSSSLSocketFactory.java

/**
* @author Kalaimaan
*/

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;

import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.commons.httpclient.HttpClientError;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;

public class EWSSSLSocketFactory implements ProtocolSocketFactory
{

private SSLContext sslcontext = null;

private SSLContext createEasySSLContext()
{
try
{
X509TrustManager trustMgr = new EWSTrustManager();
TrustManager trustMgrs[] = { trustMgr };

SSLContext context = SSLContext.getInstance(“SSL”);
context.init(null, trustMgrs, null);
return context;
}
catch (Exception e)
{
e.printStackTrace();
throw new HttpClientError(e.toString());
}
}

/**
* Retrieves SSL context.
*
* @return SSLContext.
*/
private SSLContext getSSLContext()
{
if (this.sslcontext == null)
{
this.sslcontext = createEasySSLContext();
}
return this.sslcontext;
}

/**
* @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int)
*/
public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) throws IOException,
UnknownHostException
{

return getSSLContext().getSocketFactory().createSocket(host, port, clientHost, clientPort);
}

/**
* Attempts to get a new socket connection to the given host within the
* given time limit.
* <p>
* To circumvent the limitations of older JREs that do not support connect
* timeout a controller thread is executed. The controller thread attempts
* to create a new socket within the given limit of time. If socket
* constructor does not return until the timeout expires, the controller
* terminates and throws an {@link ConnectTimeoutException}
* </p>
*
* @param host
*            (String) The host name/IP.
* @param port
*            (int) The port number on the host.
* @param localAddress
*            (InetAddress) The local host name/IP to bind the socket to.
* @param localPort
*            (int) The port number on the local machine.
* @param params
*            (HttpConnectionParams) HTTP connection parameters.
*            <p>
* @throws IOException
*             if an I/O error occurs while creating the socket.
* @throws UnknownHostException
*             if the IP address of the host cannot be determined.
*             </p>
*             <p>
* @return Socket a new socket.
*         </p>
*/
public Socket createSocket(final String host, final int port, final InetAddress localAddress, final int localPort,
final HttpConnectionParams params) throws IOException, UnknownHostException, ConnectTimeoutException
{
if (params == null)
{
throw new IllegalArgumentException(“Parameters may not be null”);
}
int timeout = params.getConnectionTimeout();
SocketFactory socketfactory = getSSLContext().getSocketFactory();
if (timeout == 0)
{
return socketfactory.createSocket(host, port, localAddress, localPort);
}
else
{
Socket socket = socketfactory.createSocket();
SocketAddress localaddr = new InetSocketAddress(localAddress, localPort);
SocketAddress remoteaddr = new InetSocketAddress(host, port);
socket.bind(localaddr);
socket.connect(remoteaddr, timeout);
return socket;
}
}

/**
* @see SecureProtocolSocketFactory#createSocket(java.lang.String,int)
*
*/
public Socket createSocket(String host, int port) throws IOException, UnknownHostException
{
return getSSLContext().getSocketFactory().createSocket(host, port);
}

/**
* @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean)
*
*/
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException,
UnknownHostException
{
return getSSLContext().getSocketFactory().createSocket(socket, host, port, autoClose);
}

public boolean equals(Object obj)
{
return ((obj != null) && obj.getClass().equals(EWSSSLSocketFactory.class));
}

public int hashCode()
{
return EWSSSLSocketFactory.class.hashCode();
}

}

File : EWSTrustManager.java

/**
* @author kalaimaan
*/

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.X509TrustManager;

public class EWSTrustManager implements X509TrustManager
{

public EWSTrustManager()
{
}

public void checkClientTrusted(X509Certificate ax509certificate[], String s) throws CertificateException
{
}

public void checkServerTrusted(X509Certificate ax509certificate[], String s) throws CertificateException
{
}

public java.security.cert.X509Certificate[] getAcceptedIssuers()
{
return null;
}

}

File : EWSSendEmail.java

import java.util.ArrayList;
import java.util.List;

import org.apache.axis2.AxisFault;
import org.apache.axis2.client.Options;
import org.apache.axis2.transport.http.HttpTransportProperties.Authenticator;
import org.apache.commons.httpclient.protocol.Protocol;

import com.microsoft.schemas.exchange.services._2006.messages.ArrayOfResponseMessagesType;
import com.microsoft.schemas.exchange.services._2006.messages.CreateItemDocument;
import com.microsoft.schemas.exchange.services._2006.messages.CreateItemResponseDocument;
import com.microsoft.schemas.exchange.services._2006.messages.CreateItemType;
import com.microsoft.schemas.exchange.services._2006.messages.ExchangeWebServiceStub;
import com.microsoft.schemas.exchange.services._2006.messages.ItemInfoResponseMessageType;
import com.microsoft.schemas.exchange.services._2006.messages.ResponseMessageType;
import com.microsoft.schemas.exchange.services._2006.messages.SendItemDocument;
import com.microsoft.schemas.exchange.services._2006.messages.SendItemResponseDocument;
import com.microsoft.schemas.exchange.services._2006.messages.SendItemType;
import com.microsoft.schemas.exchange.services._2006.types.ArrayOfRealItemsType;
import com.microsoft.schemas.exchange.services._2006.types.ArrayOfRecipientsType;
import com.microsoft.schemas.exchange.services._2006.types.BodyType;
import com.microsoft.schemas.exchange.services._2006.types.BodyTypeType;
import com.microsoft.schemas.exchange.services._2006.types.DistinguishedFolderIdNameType;
import com.microsoft.schemas.exchange.services._2006.types.DistinguishedFolderIdType;
import com.microsoft.schemas.exchange.services._2006.types.EmailAddressType;
import com.microsoft.schemas.exchange.services._2006.types.ItemIdType;
import com.microsoft.schemas.exchange.services._2006.types.MessageDispositionType;
import com.microsoft.schemas.exchange.services._2006.types.MessageType;
import com.microsoft.schemas.exchange.services._2006.types.NonEmptyArrayOfAllItemsType;
import com.microsoft.schemas.exchange.services._2006.types.NonEmptyArrayOfBaseItemIdsType;
import com.microsoft.schemas.exchange.services._2006.types.ResponseClassType;
import com.microsoft.schemas.exchange.services._2006.types.TargetFolderIdType;

/**
*
* @author Kalaimaan
*
*/
public class EWSSendEmail
{

ExchangeWebServiceStub exService;

private static String NTLM_AUT = “_NTLM_DIGEST_BASIC_AUTHENTICATION_”;

private static String NTLM_PRO = “NTLM”;

private static String HTTPS = “https”;

String exchangeURL = null;

private String[] to;
private String[] cc;
private String bcc[];
private String sub;
private String bodyText;

private String itemId = null;
private String changeKey = null;

public EWSSendEmail(String userName, String passWord)
{

String exchangeURL = “https://Manager/EWS/Exchange.asmx&#8221;;
try
{
exService = new ExchangeWebServiceStub(null, exchangeURL);
}
catch (AxisFault e)
{
e.printStackTrace();
}

checkAuthenticate(userName, passWord);
}

/**
*
*
*/
private void checkAuthenticate(String userName, String passWord)
{
Protocol AlcHttpsProtocol = new Protocol(HTTPS, new EWSSSLSocketFactory(), 443);
Protocol.registerProtocol(HTTPS, AlcHttpsProtocol);

Options options = exService._getServiceClient().getOptions();
Authenticator authenticator = new Authenticator();

List<String> authScheme = new ArrayList<String>();
authScheme.add(NTLM_PRO);

authenticator.setAuthSchemes(authScheme);
authenticator.setUsername(userName);
authenticator.setPassword(passWord);
authenticator.setHost(“Manager”);

authenticator.setDomain(exchangeURL);

authenticator.setPort(Integer.parseInt(“443”));

options.setProperty(NTLM_AUT, authenticator);

options.setUserName(userName);

exService._getServiceClient().setOptions(options);
}

/**
*
* @return
*/
public void sendEmailItem(String[] to, String[] cc, String bcc[], String sub, String bodyText)
{
String status = null;
this.to=  to;
this.cc = cc;
this.bcc = bcc;
this.sub = sub;
this.bodyText = bodyText;

MessageType message = getMessageType();

sendMessageToDraft(message);

status = sendDraftMessage(itemId, changeKey);

System.out.println(“Status : ” + status);
}

/**
*
* @return
*/
private MessageType getMessageType()
{
// Create a single e-mail message.
MessageType message = MessageType.Factory.newInstance();

EmailAddressType[] emailAddressType = null;
int index = to.length;
if (index > 0)
{
emailAddressType = new EmailAddressType[index];
message.setToRecipients(ArrayOfRecipientsType.Factory.newInstance());
for (int count = 0; count < index; count++)
{
String address = to[count];
if (address != null && address.trim().length() > 0)
{
emailAddressType[count] = EmailAddressType.Factory.newInstance();
emailAddressType[count].setEmailAddress(address);
}
}
message.getToRecipients().setMailboxArray(emailAddressType);
}

index = cc.length;
if (index > 0)
{
emailAddressType = new EmailAddressType[index];
message.setCcRecipients(ArrayOfRecipientsType.Factory.newInstance());
for (int count = 0; count < index; count++)
{
String address = cc[count];
if (address != null && address.trim().length() > 0)
{
emailAddressType[count] = EmailAddressType.Factory.newInstance();
emailAddressType[count].setEmailAddress(address);
}
}
message.getCcRecipients().setMailboxArray(emailAddressType);
}

index = bcc.length;
if (index > 0)
{
emailAddressType = new EmailAddressType[index];
message.setBccRecipients(ArrayOfRecipientsType.Factory.newInstance());
for (int count = 0; count < index; count++)
{
String address = bcc[count];
if (address != null && address.trim().length() > 0)
{
emailAddressType[count] = EmailAddressType.Factory.newInstance();
emailAddressType[count].setEmailAddress(address);
}
}
message.getBccRecipients().setMailboxArray(emailAddressType);
}

if (sub != null && sub.trim().length() > 0)
message.setSubject(sub);

String body = bodyText == null ? null : bodyText;
if (body != null && body.trim().length() > 0)
{
BodyType bodyType = BodyType.Factory.newInstance();
message.setBody(bodyType);
message.getBody().setBodyType(BodyTypeType.HTML);
message.getBody().setStringValue(bodyText);
}
message.setItemClass(“IPM.Note”);

return message;
}

/**
*
* @param message
* @return
*/
private void sendMessageToDraft(MessageType message)
{
DistinguishedFolderIdType sentitems = DistinguishedFolderIdType.Factory.newInstance();
sentitems.setId(DistinguishedFolderIdNameType.DRAFTS);

// Create the array of items that will contain the appointment.
NonEmptyArrayOfAllItemsType arrayOfItems = NonEmptyArrayOfAllItemsType.Factory.newInstance();
MessageType[] messageType = new MessageType[1];
messageType[0] = MessageType.Factory.newInstance();
arrayOfItems.setMessageArray(messageType);
arrayOfItems.setMessageArray(0, message);

CreateItemType createEmailRequest = CreateItemType.Factory.newInstance();

// Specifiy how the created items are handled
createEmailRequest.setMessageDisposition(MessageDispositionType.SAVE_ONLY);
createEmailRequest.setSavedItemFolderId(TargetFolderIdType.Factory.newInstance());
createEmailRequest.getSavedItemFolderId().setDistinguishedFolderId(sentitems);

createEmailRequest.setItems(arrayOfItems);

// Send a CreateItem request and get the CreateItem response.
CreateItemDocument createItemDocument = CreateItemDocument.Factory.newInstance();
createItemDocument.setCreateItem(createEmailRequest);

CreateItemResponseDocument createItemResponseDocument = null;
try
{
createItemResponseDocument = exService.CreateItem(createItemDocument, null, null, null, null);
}
catch (Exception e)
{
e.printStackTrace();
return;
}

ArrayOfResponseMessagesType arrayOfResponseMessagesType = createItemResponseDocument.getCreateItemResponse()
.getResponseMessages();

ItemInfoResponseMessageType[] infoResponseMessageType = arrayOfResponseMessagesType
.getCreateItemResponseMessageArray();

for (ItemInfoResponseMessageType type : infoResponseMessageType)
{
if (type.getResponseClass() == ResponseClassType.SUCCESS)
{
ArrayOfRealItemsType arrayOfRealItemsType = type.getItems();

if (arrayOfRealItemsType != null && arrayOfRealItemsType.getItemArray() != null)
{
for (MessageType itemType : arrayOfRealItemsType.getMessageArray())
{
itemId = itemType.getItemId().getId();
changeKey = itemType.getItemId().getChangeKey();
}
}
}
}
}

/**
*
* @param id
* @param key
* @return
*/
private String sendDraftMessage(String id, String key)
{
String status = “Error”;

SendItemType sendItemType = SendItemType.Factory.newInstance();

DistinguishedFolderIdType sentitems = DistinguishedFolderIdType.Factory.newInstance();
sentitems.setId(DistinguishedFolderIdNameType.SENTITEMS);

sendItemType.setSaveItemToFolder(true);
sendItemType.setSavedItemFolderId(TargetFolderIdType.Factory.newInstance());
sendItemType.getSavedItemFolderId().setDistinguishedFolderId(sentitems);

ItemIdType[] idType = new ItemIdType[1];
idType[0] = ItemIdType.Factory.newInstance();
idType[0].setId(id);
idType[0].setChangeKey(key);
NonEmptyArrayOfBaseItemIdsType baseItemIdsType = NonEmptyArrayOfBaseItemIdsType.Factory.newInstance();
baseItemIdsType.setItemIdArray(idType);

sendItemType.setItemIds(baseItemIdsType);

SendItemDocument sendItemDocument = SendItemDocument.Factory.newInstance();
sendItemDocument.setSendItem(sendItemType);

SendItemResponseDocument responseDocument = null;
try
{
responseDocument = exService.SendItem(sendItemDocument, null, null, null, null);
}
catch (Exception e)
{
e.printStackTrace();
return status;
}

ArrayOfResponseMessagesType arrayOfResponseMessagesType = responseDocument.getSendItemResponse()
.getResponseMessages();

ResponseMessageType[] sendItemResponseTypes = arrayOfResponseMessagesType.getSendItemResponseMessageArray();

for (ResponseMessageType type : sendItemResponseTypes)
{
if (type.getResponseClass() == ResponseClassType.SUCCESS)
{
System.out.println(“Id :  >>>> : ”  +id);
System.out.println(“key : >>>> : ” + key);
status = “Success”;
}
}

return status;
}
}

Output:

<!– @page { size: 8.5in 11in; margin: 0.79in } P { margin-bottom: 0.08in } –>

Id :  >>>> :  AAATAHRlc3QwMUBkb21haW4ubG9jYWwARgAAAAAAuIdR3qV3p0SYwe+85PKTjQcA1v6YTIQck0aSvXE4cDp+8wABPuROMgAA1v6YTIQck0aSvXE4cDp+8wChwpJ2OAAA

key : >>>> : CQAAABYAAADW/phMhByTRpK9cThwOn7zAKHCkotI

Status : Success


Advertisements

7 Responses to “Send Email using Exchange web service”

  1. brunee said

    Hello,

    Thank you for the excellent post! Unfortunately I am getting a 401 Auth error when trying to send an email?

    INFO] Unable to sendViaPost to url[https://office.xx.com/EWS/Exchange.asmx]
    org.apache.axis2.AxisFault: Transport error: 401 Error: Unauthorized
    at org.apache.axis2.transport.http.HTTPSender.handleResponse(HTTPSender.java:298)
    at org.apache.axis2.transport.http.HTTPSender.sendViaPost(HTTPSender.java:192)
    at org.apache.axis2.transport.http.HTTPSender.send(HTTPSender.java:77)
    at org.apache.axis2.transport.http.CommonsHTTPTransportSender.writeMessageWithCommons(CommonsHTTPTransportSender.java:327)
    at org.apache.axis2.transport.http.CommonsHTTPTransportSender.invoke(CommonsHTTPTransportSender.java:206)
    at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:396)
    at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:374)
    at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:211)
    at org.apache.axis2.client.OperationClient.execute(OperationClient.java:163)
    at com.microsoft.schemas.exchange.services._2006.messages.ExchangeServiceStub.SendItem(ExchangeServiceStub.java:3688)
    at com.xx.ews.test.EWSSendEmail.sendDraftMessage(EWSSendEmail.java:313)
    at com.xx.ews.test.EWSSendEmail.sendEmailItem(EWSSendEmail.java:131)
    at com.xx.ews.test.EWSSendEmail.main(EWSSendEmail.java:381)
    [DEBUG] org.apache.axis2.AxisFault: Transport error: 401 Error: Unauthorized
    [DEBUG] org.apache.axis2.AxisFault: Transport error: 401 Error: Unauthorized

    Have you any ideas?

    Many thanks
    Andrew

  2. kalaimaan said

    Hi Andrew,

    Check my post of exchange server it have the details SSL file namely : EWSSSLSocketFactory.java and File : EWSTrustManager.java for SSL activation.

    The below line are use to Open the SSL gateway of exchangeserver stub to do all process

    public EWSSendEmail(String userName, String passWord)
    {

    String exchangeURL = “https://Manager/EWS/Exchange.asmx”;
    try
    {
    exService = new ExchangeWebServiceStub(null, exchangeURL);
    }
    catch (AxisFault e)
    {
    e.printStackTrace();
    }

    checkAuthenticate(userName, passWord);
    }

    /**
    *
    *
    */
    private void checkAuthenticate(String userName, String passWord)
    {
    Protocol AlcHttpsProtocol = new Protocol(HTTPS, new EWSSSLSocketFactory(), 443);
    Protocol.registerProtocol(HTTPS, AlcHttpsProtocol);

    Options options = exService._getServiceClient().getOptions();
    Authenticator authenticator = new Authenticator();

    List authScheme = new ArrayList();
    authScheme.add(NTLM_PRO);

    authenticator.setAuthSchemes(authScheme);
    authenticator.setUsername(userName);
    authenticator.setPassword(passWord);
    authenticator.setHost(”Manager”);

    authenticator.setDomain(exchangeURL);

    authenticator.setPort(Integer.parseInt(”443″));

    options.setProperty(NTLM_AUT, authenticator);

    options.setUserName(userName);

    exService._getServiceClient().setOptions(options);
    }

    have a look again and your problem will clear

  3. Brunee said

    Hi kalaimaan,

    I have already done this, the SSL is good. I also downloaded the JEC EWSJ library, and I got the same 401, so it must be something on my Exchange server. I am using SBS2008 with SP1. I did tinker with permissions a few weeks ago as I was trying to get WebDav to work, so maybe I messed it up.

    Do you know if there are any links or do you have any info on how SBS2008 should be setup to enable authentication?

    Thanks heaps
    Andrew

  4. kalaimaan said

    Hi Andrew,

    I have one clarification, do you changes the class name of EWSSSLSocketFactory.java and possible paste the current ssl file which you have .. here i will check and let back to you

    kalaimaan

  5. brunee said

    Here is is

    public class EWSSSLSocketFactory implements ProtocolSocketFactory {

    private SSLContext sslcontext = null;

    private SSLContext createEasySSLContext() {
    try {
    X509TrustManager trustMgr = new EWSTrustManager();
    TrustManager trustMgrs[] = { trustMgr };

    SSLContext context = SSLContext.getInstance("SSL");
    context.init(null, trustMgrs, null);
    return context;
    } catch (Exception e) {
    e.printStackTrace();
    throw new HttpClientError(e.toString());
    }
    }

    /**
    * Retrieves SSL context.
    *
    * @return SSLContext.
    */
    private SSLContext getSSLContext() {
    if (this.sslcontext == null) {
    this.sslcontext = createEasySSLContext();
    }
    return this.sslcontext;
    }

    /**
    * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int)
    */
    public Socket createSocket(String host, int port, InetAddress clientHost,
    int clientPort) throws IOException, UnknownHostException {

    return getSSLContext().getSocketFactory().createSocket(host, port,
    clientHost, clientPort);
    }

    /**
    * Attempts to get a new socket connection to the given host within the
    * given time limit.
    *
    * To circumvent the limitations of older JREs that do not support connect
    * timeout a controller thread is executed. The controller thread attempts
    * to create a new socket within the given limit of time. If socket
    * constructor does not return until the timeout expires, the controller
    * terminates and throws an {@link ConnectTimeoutException}
    *
    *
    * @param host
    * (String) The host name/IP.
    * @param port
    * (int) The port number on the host.
    * @param localAddress
    * (InetAddress) The local host name/IP to bind the socket to.
    * @param localPort
    * (int) The port number on the local machine.
    * @param params
    * (HttpConnectionParams) HTTP connection parameters.
    *
    * @throws IOException
    * if an I/O error occurs while creating the socket.
    * @throws UnknownHostException
    * if the IP address of the host cannot be determined.
    *
    *
    * @return Socket a new socket.
    *
    */
    public Socket createSocket(final String host, final int port,
    final InetAddress localAddress, final int localPort,
    final HttpConnectionParams params) throws IOException,
    UnknownHostException, ConnectTimeoutException {
    if (params == null) {
    }
    int timeout = params.getConnectionTimeout();
    SocketFactory socketfactory = getSSLContext().getSocketFactory();
    if (timeout == 0) {
    return socketfactory.createSocket(host, port, localAddress,
    localPort);
    } else {
    Socket socket = socketfactory.createSocket();
    SocketAddress localaddr = new InetSocketAddress(localAddress,
    localPort);
    SocketAddress remoteaddr = new InetSocketAddress(host, port);
    socket.bind(localaddr);
    socket.connect(remoteaddr, timeout);
    return socket;
    }
    }

    /**
    * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int)
    *
    */
    public Socket createSocket(String host, int port) throws IOException,
    UnknownHostException {
    return getSSLContext().getSocketFactory().createSocket(host, port);
    }

    /**
    * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean)
    *
    */
    public Socket createSocket(Socket socket, String host, int port,
    boolean autoClose) throws IOException, UnknownHostException {
    return getSSLContext().getSocketFactory().createSocket(socket, host,
    port, autoClose);
    }

    public boolean equals(Object obj) {
    return ((obj != null) && obj.getClass().equals(
    EWSSSLSocketFactory.class));
    }

    public int hashCode() {
    return EWSSSLSocketFactory.class.hashCode();
    }

    }

  6. kalaimaan said

    Hi Andrew,

    There is no mistake in SSL factory, do you create your stub correctly ?

    why because the stub package also very important. Please check the EWS stub package and let me know

  7. control mantenimiento…

    […]Send Email using Exchange web service « Kalaimaan[…]…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: