9

I am writing a Java application to download emails using Exchange Web Services. I am using Microsoft's ewsjava API for doing this.

I am able to fetch email headers. But, I am not able to download email attachments using this API. Below is the code snippet.

FolderId folderId = new FolderId(WellKnownFolderName.Inbox, "mailbox@example.com");
findResults = service.findItems(folderId, view);
for(Item item : findResults.getItems()) {
   if (item.getHasAttachments()) {
      AttachmentCollection attachmentsCol = item.getAttachments();
      System.out.println(attachmentsCol.getCount()); // This is printing zero all the time. My message has one attachment.
      for (int i = 0; i < attachmentsCol.getCount(); i++) {
         FileAttachment attachment = (FileAttachment)attachmentsCol.getPropertyAtIndex(i);
         String name = attachment.getFileName();
         int size = attachment.getContent().length;
      }
   }
}

item.getHasAttachments() is returning true, but attachmentsCol.getCount() is 0.

JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
NareshPS
  • 103
  • 1
  • 1
  • 4

5 Answers5

8

You need to load property Attachments before you can use them in your code. You set it for ItemView object that you pass to FindItems method.

Or you can first find items and then call service.LoadPropertiesForItems and pass findIesults and PropertySet object with added EmailMessageSchema.Attachments

grapkulec
  • 1,022
  • 13
  • 28
4
FolderId folderId = new FolderId(WellKnownFolderName.Inbox, "mailbox@example.com"); 
findResults = service.findItems(folderId, view); 
service.loadPropertiesForItems(findResults, new PropertySet(BasePropertySet.FirstClassProperties, EmailMessageSchema.Attachments));

for(Item item : findResults.getItems()) { 
   if (item.getHasAttachments()) { 
      AttachmentCollection attachmentsCol = item.getAttachments(); 
      System.out.println(attachmentsCol.getCount());
      for (int i = 0; i < attachmentsCol.getCount(); i++) { 
         FileAttachment attachment = (FileAttachment)attachmentsCol.getPropertyAtIndex(i); 
         attachment.load(attachment.getName());
      } 
   } 
} 
Yury
  • 41
  • 2
  • 1
    while your answer might work, it could use some comment on what your code is doing, or what you have changed from OP's code! – codeling Sep 18 '12 at 10:40
  • @Yury: If I've read well, you have literally added a single line. Consider trimming the code and just explaining what it does and why it is needed – quetzalcoatl Sep 25 '12 at 18:21
1

Honestly as painful as it is, I'd use the PROXY version instead of the Managed API. It's a pity, but the managed version for java seems riddled with bugs.

MJB
  • 9,352
  • 6
  • 34
  • 49
  • I can't seem to find any references for this? Could you provide a link? – Black Apr 04 '17 at 01:38
  • It's just what you get when you run wsimport or other such codegens against the raw WSDL. https://msdn.microsoft.com/en-us/library/office/dd877302(v=exchg.150).aspx – MJB Apr 04 '17 at 17:49
0

before checking for item.getHasAttachments(), you should do item.load(). Otherwise there is a chance your code will not load the attachment and attachmentsCol.getCount() will be 0. Working code with Exchange Server 2010 :

ItemView view = new ItemView(Integer.MAX_VALUE);
view.getOrderBy().add(ItemSchema.DateTimeReceived, SortDirection.Descending);  
FindItemsResults < Item > results = service.findItems(WellKnownFolderName.Inbox, new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, true), view);
Iterator<Item> itr = results.iterator();
while(itr.hasNext()) {
    Item item = itr.next();
    item.load();
    ItemId itemId = item.getId();
    EmailMessage email = EmailMessage.bind(service, itemId);
    if (item.getHasAttachments()) { 
        System.err.println(item.getAttachments());
        AttachmentCollection attachmentsCol = item.getAttachments(); 
        for (int i = 0; i < attachmentsCol.getCount(); i++) {
            FileAttachment attachment=(FileAttachment)attachmentsCol.getPropertyAtIndex(i);
            attachment.load("C:\\TEMP\\" +attachment.getName());
        }
    }
}
Anant Agarwal
  • 63
  • 1
  • 10
  • when I call `load()` I get `microsoft.exchange.webservices.data.core.exception.service.remote.ServiceRequestException: The request failed. ParseError at [row,col]:[93,9101] Message: Character reference "` – Black Apr 04 '17 at 01:50
  • @Black - that's because the attachment may be an Item Attachment which has some special characters in the body or subject line. that is a know issue. https://github.com/OfficeDev/ews-java-api/issues/440 – Lucky Apr 12 '17 at 15:05
  • Doesn't this issue make the EWS api totally non-viable? – Black Apr 13 '17 at 00:47
  • I found the solution in a patch available here: https://github.com/RavnSystems/ews-java-api/commit/845f20fe1e33cbb1e7c5020df3de6291b56268dd – Black May 09 '17 at 00:39
0

Little late for the answer, but here is what I have.

HashMap<String, HashMap<String, String>> attachments = new HashMap<String, HashMap<String, String>>();    

if (emailMessage.getHasAttachments() || emailMessage.getAttachments().getItems().size() > 0) {

            //get all the attachments
            AttachmentCollection attachmentsCol = emailMessage.getAttachments();

            log.info("File Count: " +attachmentsCol.getCount());

            //loop over the attachments
            for (int i = 0; i < attachmentsCol.getCount(); i++) {
                Attachment attachment = attachmentsCol.getPropertyAtIndex(i);
                //log.debug("Starting to process attachment "+ attachment.getName());

                   //FileAttachment - Represents a file that is attached to an email item
                    if (attachment instanceof FileAttachment || attachment.getIsInline()) {

                        attachments.putAll(extractFileAttachments(attachment, properties));

                    } else if (attachment instanceof ItemAttachment) { //ItemAttachment - Represents an Exchange item that is attached to another Exchange item.

                        attachments.putAll(extractItemAttachments(service, attachment, properties, appendedBody));
                    }
                }
            }
        } else {
            log.debug("Email message does not have any attachments.");
        }


//Extract File Attachments
try {
        FileAttachment fileAttachment = (FileAttachment) attachment;
        // if we don't call this, the Content property may be null.
        fileAttachment.load();

        //extract the attachment content, it's not base64 encoded.
        attachmentContent = fileAttachment.getContent();

        if (attachmentContent != null && attachmentContent.length > 0) {

            //check the size
            int attachmentSize = attachmentContent.length;

            //check if the attachment is valid
            ValidateEmail.validateAttachment(fileAttachment, properties,
                    emailIdentifier, attachmentSize);

            fileAttachments.put(UtilConstants.ATTACHMENT_SIZE, String.valueOf(attachmentSize));

            //get attachment name
            String fileName = fileAttachment.getName();
            fileAttachments.put(UtilConstants.ATTACHMENT_NAME, fileName);

            String mimeType = fileAttachment.getContentType();
            fileAttachments.put(UtilConstants.ATTACHMENT_MIME_TYPE, mimeType);

            log.info("File Name: " + fileName + "  File Size: " + attachmentSize);


            if (attachmentContent != null && attachmentContent.length > 0) {
                //convert the content to base64 encoded string and add to the collection.
                String base64Encoded = UtilFunctions.encodeToBase64(attachmentContent);
                fileAttachments.put(UtilConstants.ATTACHMENT_CONTENT, base64Encoded);
            }



//Extract Item Attachment
try {
        ItemAttachment itemAttachment = (ItemAttachment) attachment;

        PropertySet propertySet = new PropertySet(
                BasePropertySet.FirstClassProperties, ItemSchema.Attachments, 
                ItemSchema.Body, ItemSchema.Id, ItemSchema.DateTimeReceived,
                EmailMessageSchema.DateTimeReceived, EmailMessageSchema.Body);

        itemAttachment.load();
        propertySet.setRequestedBodyType(BodyType.Text);

        Item item = itemAttachment.getItem();

        eBody = appendItemBody(item, appendedBody.get(UtilConstants.BODY_CONTENT));

        appendedBody.put(UtilConstants.BODY_CONTENT, eBody);

        /*
         * We need to check if Item attachment has further more
         * attachments like .msg attachment, which is an outlook email
         * as attachment. Yes, we can attach an email chain as
         * attachment and that email chain can have multiple
         * attachments.
         */
        AttachmentCollection childAttachments = item.getAttachments();
        //check if not empty collection. move on
        if (childAttachments != null && !childAttachments.getItems().isEmpty() && childAttachments.getCount() > 0) {

            for (Attachment childAttachment : childAttachments) {

                if (childAttachment instanceof FileAttachment) {

                    itemAttachments.putAll(extractFileAttachments(childAttachment, properties, emailIdentifier));

                } else if (childAttachment instanceof ItemAttachment) {

                    itemAttachments = extractItemAttachments(service, childAttachment, properties, appendedBody, emailIdentifier);
                }
            }
        }
    } catch (Exception e) {
        throw new Exception("Exception while extracting Item Attachments: " + e.getMessage());
    }
Lucky
  • 783
  • 2
  • 10
  • 28