ews-java-api icon indicating copy to clipboard operation
ews-java-api copied to clipboard

Send email with binary extended property (voting options)

Open tlsedev opened this issue 9 years ago • 4 comments

Hi,

I need to send an email with voting options (Yes, No) and after reading the documentation here it seems i have to use the extended property of Binary type with id 0x00008520.

I used the API to retrieve a mail containing voting options i sent with outlook and i used the binary content of the extended property to send a new email. But it's not working, the value of the extended property seems to be always null. Here is the code i used :

ExtendedPropertyDefinition votingButtonProperty = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.Common, 0x8520, MapiPropertyType.Binary);

EmailMessage extendedPropertyMail = EmailMessage.bind(service, email.getId(), new PropertySet(votingButtonProperty));

for(ExtendedProperty property : extendedPropertyMail.getExtendedProperties()) {
    if(property.getPropertyDefinition().getId().intValue() == 0x8520) {
        EmailMessage msg = new EmailMessage(service);
        // Set subject and recipients ...
        msg.setExtendedProperty(votingButtonProperty, property.getValue());
        msg.send();
    }
}

When i look at the source code, it seems we cannot add extendedProperty of type byte[] for MapiPropertyType.Binary, it has to be an array of Byte as we can see in MapiTypeConverter.java:

mapitype = new MapiTypeConverterMapEntry(Byte[].class);
mapitype.setParse(IFunctions.Base64Decoder.INSTANCE);
mapitype.setConvertToString(IFunctions.Base64Encoder.INSTANCE);
map.put(MapiPropertyType.Binary, mapitype);

And if i convert the byte array to Byte array before calling msg.setExtendedProperty(votingButtonProperty, property.getValue());, then i get a ClassCastException : Cannot cast Byte[] to byte[] when executing this code (L82 - IFunctions.java) :

public static class Base64Encoder implements IFunction<Object, String> {
    public static final Base64Encoder INSTANCE = new Base64Encoder();
    public String func(final Object o) {
        return Base64.encodeBase64String((byte[]) o);
    }
}

Can you tell me if i'm doing this wrong and point me in the right direction ?

Thank you

tlsedev avatar Dec 01 '15 15:12 tlsedev

Same question from me

mallen avatar Jun 16 '16 09:06 mallen

I am having this problem as well.

I checked out the projected and modified IFunctions.java to encode a Byte[] as base 64 just like it does for a byte[]. Now I can pass a Byte[] to setExtendedProperty. This works.

However, based on the fact that the C# and PowerShell libraries accept a byte[] to set extended properties with type MapiPropertyType.Binary, I'm guessing this is a bug in the library.

I considered changing the mapping in MapiTypeConverter so that MapiPropertyType.Binary would map to byte[] since MapiPropertyType.BinaryArray already maps to Byte[], but this broke some unit tests. I'll need to do some more research to see if the unit tests are wrong, or if this is not a valid change.

I'd like to work with someone with more experience with this project to create a pull request to fix this issue.

In the meantime, making the following change to IFunctions.java allows you to send emails with voting buttons.

  public static class Base64Encoder implements IFunction<Object, String> {
    public static final Base64Encoder INSTANCE = new Base64Encoder();

//    public String func(final Object o) {
//      return Base64.encodeBase64String((byte[]) o);
//    }

    public String func(final Object o) {
      if (o instanceof Byte[]) {
        Byte[] source = (Byte[]) o;
        byte [] bytes = new byte[source.length];
        for (int i = 0; i < source.length; i++) {
          if (source[i] == null) {
            throw new NullPointerException("source array may not contain nulls");
          }
          bytes[i] = source[i];
        }
        return Base64.encodeBase64String(bytes);
	  } else {
        return Base64.encodeBase64String((byte[]) o);
	  }
    }
  }

tim93422 avatar Dec 11 '17 19:12 tim93422

Here is an alternative fix that changes the registration from Byte[] to byte[] without breaking the tests: https://github.com/FacilityNet/ews-java-api/commit/d13f40763be6667ca6e84183b79769710083707f

soerenBoisen avatar Feb 07 '20 10:02 soerenBoisen

can we have a proper example of sending / receiving with voting actions of users?

imranrajjad avatar Apr 05 '21 10:04 imranrajjad