001 /*
002 * The MIT License
003 * Copyright (c) 2012 Microsoft Corporation
004 *
005 * Permission is hereby granted, free of charge, to any person obtaining a copy
006 * of this software and associated documentation files (the "Software"), to deal
007 * in the Software without restriction, including without limitation the rights
008 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
009 * copies of the Software, and to permit persons to whom the Software is
010 * furnished to do so, subject to the following conditions:
011 *
012 * The above copyright notice and this permission notice shall be included in
013 * all copies or substantial portions of the Software.
014 *
015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
016 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
017 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
018 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
019 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
020 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
021 * THE SOFTWARE.
022 */
023
024 package microsoft.exchange.webservices.data.core.service.item;
025
026 import microsoft.exchange.webservices.data.attribute.Attachable;
027 import microsoft.exchange.webservices.data.attribute.ServiceObjectDefinition;
028 import microsoft.exchange.webservices.data.core.EwsUtilities;
029 import microsoft.exchange.webservices.data.core.ExchangeService;
030 import microsoft.exchange.webservices.data.core.PropertySet;
031 import microsoft.exchange.webservices.data.core.XmlElementNames;
032 import microsoft.exchange.webservices.data.core.service.response.ResponseMessage;
033 import microsoft.exchange.webservices.data.core.service.response.SuppressReadReceipt;
034 import microsoft.exchange.webservices.data.core.service.schema.EmailMessageSchema;
035 import microsoft.exchange.webservices.data.core.service.schema.ServiceObjectSchema;
036 import microsoft.exchange.webservices.data.core.enumeration.service.ConflictResolutionMode;
037 import microsoft.exchange.webservices.data.core.enumeration.misc.ExchangeVersion;
038 import microsoft.exchange.webservices.data.core.enumeration.service.MessageDisposition;
039 import microsoft.exchange.webservices.data.core.enumeration.service.ResponseMessageType;
040 import microsoft.exchange.webservices.data.core.enumeration.property.WellKnownFolderName;
041 import microsoft.exchange.webservices.data.core.exception.service.local.ServiceLocalException;
042 import microsoft.exchange.webservices.data.property.complex.EmailAddress;
043 import microsoft.exchange.webservices.data.property.complex.EmailAddressCollection;
044 import microsoft.exchange.webservices.data.property.complex.FolderId;
045 import microsoft.exchange.webservices.data.property.complex.ItemAttachment;
046 import microsoft.exchange.webservices.data.property.complex.ItemId;
047 import microsoft.exchange.webservices.data.property.complex.MessageBody;
048
049 import java.util.Arrays;
050
051 /**
052 * Represents an e-mail message. Properties available on e-mail messages are
053 * defined in the EmailMessageSchema class.
054 */
055 @Attachable
056 @ServiceObjectDefinition(xmlElementName = XmlElementNames.Message)
057 public class EmailMessage extends Item {
058
059 /**
060 * Initializes an unsaved local instance of EmailMessage. To bind to an
061 * existing e-mail message, use EmailMessage.Bind() instead.
062 *
063 * @param service The ExchangeService object to which the e-mail message will be
064 * bound.
065 * @throws Exception the exception
066 */
067 public EmailMessage(ExchangeService service) throws Exception {
068 super(service);
069 }
070
071 /**
072 * Initializes a new instance of the "EmailMessage" class.
073 *
074 * @param parentAttachment The parent attachment.
075 * @throws Exception the exception
076 */
077 public EmailMessage(ItemAttachment parentAttachment) throws Exception {
078 super(parentAttachment);
079 }
080
081 /**
082 * Binds to an existing e-mail message and loads the specified set of
083 * property.Calling this method results in a call to EWS.
084 *
085 * @param service the service
086 * @param id the id
087 * @param propertySet the property set
088 * @return An EmailMessage instance representing the e-mail message
089 * corresponding to the specified Id
090 * @throws Exception the exception
091 */
092 public static EmailMessage bind(ExchangeService service, ItemId id,
093 PropertySet propertySet) throws Exception {
094 return service.bindToItem(EmailMessage.class, id, propertySet);
095
096 }
097
098 /**
099 * Binds to an existing e-mail message and loads its first class
100 * property.Calling this method results in a call to EWS.
101 *
102 * @param service the service
103 * @param id the id
104 * @return An EmailMessage instance representing the e-mail message
105 * corresponding to the specified Id
106 * @throws Exception the exception
107 */
108 public static EmailMessage bind(ExchangeService service, ItemId id)
109 throws Exception {
110 return EmailMessage.bind(service, id, PropertySet
111 .getFirstClassProperties());
112 }
113
114 /**
115 * Method to return the schema associated with this type of object.
116 *
117 * @return The schema associated with this type of object.
118 */
119 @Override public ServiceObjectSchema getSchema() {
120 return EmailMessageSchema.Instance;
121 }
122
123 /**
124 * Gets the minimum required server version.
125 *
126 * @return Earliest Exchange version in which this service object type is
127 * supported.
128 */
129 @Override public ExchangeVersion getMinimumRequiredServerVersion() {
130 return ExchangeVersion.Exchange2007_SP1;
131 }
132
133 /**
134 * Send message.
135 *
136 * @param parentFolderId The parent folder id.
137 * @param messageDisposition The message disposition.
138 * @throws Exception the exception
139 */
140 private void internalSend(FolderId parentFolderId,
141 MessageDisposition messageDisposition) throws Exception {
142 this.throwIfThisIsAttachment();
143
144 if (this.isNew()) {
145 if ((this.getAttachments().getCount() == 0) ||
146 (messageDisposition == MessageDisposition.SaveOnly)) {
147 this.internalCreate(parentFolderId, messageDisposition, null);
148 } else {
149 // Bug E14:80316 -- If the message has attachments, save as a
150 // draft (and add attachments) before sending.
151 this.internalCreate(null, // null means use the Drafts folder in
152 // the mailbox of the authenticated
153 // user.
154 MessageDisposition.SaveOnly, null);
155
156 this.getService().sendItem(this, parentFolderId);
157 }
158 } else if (this.isDirty()) {
159 // Validate and save attachments before sending.
160 this.getAttachments().validate();
161 this.getAttachments().save();
162
163 if (this.getPropertyBag().getIsUpdateCallNecessary()) {
164 this.internalUpdate(parentFolderId,
165 ConflictResolutionMode.AutoResolve, messageDisposition,
166 null);
167 } else {
168 this.getService().sendItem(this, parentFolderId);
169 }
170 } else {
171 this.getService().sendItem(this, parentFolderId);
172 }
173
174 // this.internalCreate(parentFolderId, messageDisposition, null);
175 }
176
177 /**
178 * Creates a reply response to the message.
179 *
180 * @param replyAll the reply all
181 * @return A ResponseMessage representing the reply response that can
182 * subsequently be modified and sent.
183 * @throws Exception the exception
184 */
185 public ResponseMessage createReply(boolean replyAll) throws Exception {
186 this.throwIfThisIsNew();
187
188 return new ResponseMessage(this,
189 replyAll ? ResponseMessageType.ReplyAll :
190 ResponseMessageType.Reply);
191 }
192
193 /**
194 * Creates a forward response to the message.
195 *
196 * @return A ResponseMessage representing the forward response that can
197 * subsequently be modified and sent.
198 * @throws Exception the exception
199 */
200 public ResponseMessage createForward() throws Exception {
201 this.throwIfThisIsNew();
202 return new ResponseMessage(this, ResponseMessageType.Forward);
203 }
204
205 /**
206 * Replies to the message. Calling this method results in a call to EWS.
207 *
208 * @param bodyPrefix the body prefix
209 * @param replyAll the reply all
210 * @throws Exception the exception
211 */
212 public void reply(MessageBody bodyPrefix, boolean replyAll)
213 throws Exception {
214 ResponseMessage responseMessage = this.createReply(replyAll);
215 responseMessage.setBodyPrefix(bodyPrefix);
216 responseMessage.sendAndSaveCopy();
217 }
218
219 /**
220 * Forwards the message. Calling this method results in a call to EWS.
221 *
222 * @param bodyPrefix the body prefix
223 * @param toRecipients the to recipients
224 * @throws Exception the exception
225 */
226 public void forward(MessageBody bodyPrefix, EmailAddress... toRecipients)
227 throws Exception {
228 if (null != toRecipients) {
229 forward(bodyPrefix, Arrays.asList(toRecipients));
230 }
231 }
232
233 /**
234 * Forwards the message. Calling this method results in a call to EWS.
235 *
236 * @param bodyPrefix the body prefix
237 * @param toRecipients the to recipients
238 * @throws Exception the exception
239 */
240 public void forward(MessageBody bodyPrefix,
241 Iterable<EmailAddress> toRecipients) throws Exception {
242 ResponseMessage responseMessage = this.createForward();
243
244 responseMessage.setBodyPrefix(bodyPrefix);
245 responseMessage.getToRecipients()
246 .addEmailRange(toRecipients.iterator());
247
248 responseMessage.sendAndSaveCopy();
249 }
250
251 /**
252 * Sends this e-mail message. Calling this method results in at least one
253 * call to EWS.
254 *
255 * @throws Exception the exception
256 */
257 public void send() throws Exception {
258 internalSend(null, MessageDisposition.SendOnly);
259 }
260
261 /**
262 * Sends this e-mail message and saves a copy of it in the specified
263 * folder. SendAndSaveCopy does not work if the message has unsaved
264 * attachments. In that case, the message must first be saved and then sent.
265 * Calling this method results in a call to EWS.
266 *
267 * @param destinationFolderId the destination folder id
268 * @throws Exception the exception
269 */
270 public void sendAndSaveCopy(FolderId destinationFolderId) throws Exception {
271 EwsUtilities.validateParam(destinationFolderId, "destinationFolderId");
272 this.internalSend(destinationFolderId,
273 MessageDisposition.SendAndSaveCopy);
274 }
275
276 /**
277 * Sends this e-mail message and saves a copy of it in the specified
278 * folder. SendAndSaveCopy does not work if the message has unsaved
279 * attachments. In that case, the message must first be saved and then sent.
280 * Calling this method results in a call to EWS.
281 *
282 * @param destinationFolderName the destination folder name
283 * @throws Exception the exception
284 */
285 public void sendAndSaveCopy(WellKnownFolderName destinationFolderName)
286 throws Exception {
287 this.internalSend(new FolderId(destinationFolderName),
288 MessageDisposition.SendAndSaveCopy);
289 }
290
291 /**
292 * Sends this e-mail message and saves a copy of it in the Sent Items
293 * folder. SendAndSaveCopy does not work if the message has unsaved
294 * attachments. In that case, the message must first be saved and then sent.
295 * Calling this method results in a call to EWS.
296 *
297 * @throws Exception the exception
298 */
299 public void sendAndSaveCopy() throws Exception {
300 this.internalSend(new FolderId(WellKnownFolderName.SentItems),
301 MessageDisposition.SendAndSaveCopy);
302 }
303
304 /**
305 * Suppresses the read receipt on the message. Calling this method results
306 * in a call to EWS.
307 *
308 * @throws Exception the exception
309 */
310 public void suppressReadReceipt() throws Exception {
311 this.throwIfThisIsNew();
312 new SuppressReadReceipt(this).internalCreate(null, null);
313 }
314
315 /**
316 * Gets the list of To recipients for the e-mail message.
317 *
318 * @return The list of To recipients for the e-mail message.
319 * @throws ServiceLocalException the service local exception
320 */
321 public EmailAddressCollection getToRecipients()
322 throws ServiceLocalException {
323 return getPropertyBag().getObjectFromPropertyDefinition(
324 EmailMessageSchema.ToRecipients);
325 }
326
327 /**
328 * Gets the list of Bcc recipients for the e-mail message.
329 *
330 * @return the bcc recipients
331 * @throws ServiceLocalException the service local exception
332 */
333 public EmailAddressCollection getBccRecipients()
334 throws ServiceLocalException {
335 return getPropertyBag().getObjectFromPropertyDefinition(
336 EmailMessageSchema.BccRecipients);
337 }
338
339 /**
340 * Gets the list of Cc recipients for the e-mail message.
341 *
342 * @return the cc recipients
343 * @throws ServiceLocalException the service local exception
344 */
345 public EmailAddressCollection getCcRecipients()
346 throws ServiceLocalException {
347 return getPropertyBag().getObjectFromPropertyDefinition(
348 EmailMessageSchema.CcRecipients);
349 }
350
351 /**
352 * Gets the conversation topic of the e-mail message.
353 *
354 * @return the conversation topic
355 * @throws ServiceLocalException the service local exception
356 */
357 public String getConversationTopic() throws ServiceLocalException {
358 return getPropertyBag().getObjectFromPropertyDefinition(
359 EmailMessageSchema.ConversationTopic);
360 }
361
362 /**
363 * Gets the conversation index of the e-mail message.
364 *
365 * @return the conversation index
366 * @throws ServiceLocalException the service local exception
367 */
368 public byte[] getConversationIndex() throws ServiceLocalException {
369 return getPropertyBag().getObjectFromPropertyDefinition(
370 EmailMessageSchema.ConversationIndex);
371 }
372
373 /**
374 * Gets the "on behalf" sender of the e-mail message.
375 *
376 * @return the from
377 * @throws ServiceLocalException the service local exception
378 */
379 public EmailAddress getFrom() throws ServiceLocalException {
380 return getPropertyBag().getObjectFromPropertyDefinition(
381 EmailMessageSchema.From);
382 }
383
384 /**
385 * Sets the from.
386 *
387 * @param value the new from
388 * @throws Exception the exception
389 */
390 public void setFrom(EmailAddress value) throws Exception {
391 this.getPropertyBag().setObjectFromPropertyDefinition(
392 EmailMessageSchema.From, value);
393 }
394
395 /**
396 * Gets a value indicating whether this is an associated message.
397 *
398 * @return the checks if is associated
399 * @throws ServiceLocalException the service local exception
400 */
401 public boolean getIsAssociated() throws ServiceLocalException {
402 return super.getIsAssociated();
403 }
404
405 // The "new" keyword is used to expose the setter only on Message types,
406 // because
407 // EWS only supports creation of FAI Message types. IsAssociated is a
408 // readonly
409 // property of the Item type but it is used by the CreateItem web method for
410 // creating
411 // associated messages.
412
413 /**
414 * Sets the checks if is associated.
415 *
416 * @param value the new checks if is associated
417 * @throws Exception the exception
418 */
419 public void setIsAssociated(boolean value) throws Exception {
420 this.getPropertyBag().setObjectFromPropertyDefinition(
421 EmailMessageSchema.IsAssociated, value);
422 }
423
424 /**
425 * Gets a value indicating whether a read receipt is requested for
426 * the e-mail message.
427 *
428 * @return the checks if is delivery receipt requested
429 * @throws ServiceLocalException the service local exception
430 */
431 public Boolean getIsDeliveryReceiptRequested()
432 throws ServiceLocalException {
433 return getPropertyBag().getObjectFromPropertyDefinition(
434 EmailMessageSchema.IsDeliveryReceiptRequested);
435 }
436
437 /**
438 * Sets the checks if is delivery receipt requested.
439 *
440 * @param value the new checks if is delivery receipt requested
441 * @throws Exception the exception
442 */
443 public void setIsDeliveryReceiptRequested(Boolean value) throws Exception {
444 this.getPropertyBag().setObjectFromPropertyDefinition(
445 EmailMessageSchema.IsDeliveryReceiptRequested, value);
446 }
447
448 /**
449 * Gets a value indicating whether the e-mail message is read.
450 *
451 * @return the checks if is read
452 * @throws ServiceLocalException the service local exception
453 */
454 public Boolean getIsRead() throws ServiceLocalException {
455 return getPropertyBag().getObjectFromPropertyDefinition(
456 EmailMessageSchema.IsRead);
457 }
458
459 /**
460 * Sets the checks if is read.
461 *
462 * @param value the new checks if is read
463 * @throws Exception the exception
464 */
465 public void setIsRead(Boolean value) throws Exception {
466 this.getPropertyBag().setObjectFromPropertyDefinition(
467 EmailMessageSchema.IsRead, value);
468 }
469
470 /**
471 * Gets a value indicating whether a read receipt is requested for
472 * the e-mail message.
473 *
474 * @return the checks if is read receipt requested
475 * @throws ServiceLocalException the service local exception
476 */
477 public Boolean getIsReadReceiptRequested() throws ServiceLocalException {
478 return getPropertyBag().getObjectFromPropertyDefinition(
479 EmailMessageSchema.IsReadReceiptRequested);
480 }
481
482 /**
483 * Sets the checks if is read receipt requested.
484 *
485 * @param value the new checks if is read receipt requested
486 * @throws Exception the exception
487 */
488 public void setIsReadReceiptRequested(Boolean value) throws Exception {
489 this.getPropertyBag().setObjectFromPropertyDefinition(
490 EmailMessageSchema.IsReadReceiptRequested, value);
491 }
492
493 /**
494 * Gets a value indicating whether a response is requested for the
495 * e-mail message.
496 *
497 * @return the checks if is response requested
498 * @throws ServiceLocalException the service local exception
499 */
500 public Boolean getIsResponseRequested() throws ServiceLocalException {
501 return getPropertyBag().getObjectFromPropertyDefinition(
502 EmailMessageSchema.IsResponseRequested);
503 }
504
505 /**
506 * Sets the checks if is response requested.
507 *
508 * @param value the new checks if is response requested
509 * @throws Exception the exception
510 */
511 public void setIsResponseRequested(Boolean value) throws Exception {
512 this.getPropertyBag().setObjectFromPropertyDefinition(
513 EmailMessageSchema.IsResponseRequested, value);
514 }
515
516 /**
517 * Gets the Internat Message Id of the e-mail message.
518 *
519 * @return the internet message id
520 * @throws ServiceLocalException the service local exception
521 */
522 public String getInternetMessageId() throws ServiceLocalException {
523 return getPropertyBag().getObjectFromPropertyDefinition(
524 EmailMessageSchema.InternetMessageId);
525 }
526
527 /**
528 * Gets the references of the e-mail message.
529 *
530 * @return the references
531 * @throws ServiceLocalException the service local exception
532 */
533 public String getReferences() throws ServiceLocalException {
534 return getPropertyBag().getObjectFromPropertyDefinition(
535 EmailMessageSchema.References);
536 }
537
538 /**
539 * Sets the references.
540 *
541 * @param value the new references
542 * @throws Exception the exception
543 */
544 public void setReferences(String value) throws Exception {
545 this.getPropertyBag().setObjectFromPropertyDefinition(
546 EmailMessageSchema.References, value);
547 }
548
549 /**
550 * Gets a list of e-mail addresses to which replies should be addressed.
551 *
552 * @return the reply to
553 * @throws ServiceLocalException the service local exception
554 */
555 public EmailAddressCollection getReplyTo() throws ServiceLocalException {
556 return getPropertyBag().getObjectFromPropertyDefinition(
557 EmailMessageSchema.ReplyTo);
558 }
559
560 /**
561 * Gets the sender of the e-mail message.
562 *
563 * @return the sender
564 * @throws ServiceLocalException the service local exception
565 */
566 public EmailAddress getSender() throws ServiceLocalException {
567 return getPropertyBag().getObjectFromPropertyDefinition(
568 EmailMessageSchema.Sender);
569 }
570
571 /**
572 * Sets the sender.
573 *
574 * @param value the new sender
575 * @throws Exception the exception
576 */
577 public void setSender(EmailAddress value) throws Exception {
578 this.getPropertyBag().setObjectFromPropertyDefinition(
579 EmailMessageSchema.Sender, value);
580 }
581
582 /**
583 * Gets the ReceivedBy property of the e-mail message.
584 *
585 * @return the received by
586 * @throws ServiceLocalException the service local exception
587 */
588 public EmailAddress getReceivedBy() throws ServiceLocalException {
589 return getPropertyBag().getObjectFromPropertyDefinition(
590 EmailMessageSchema.ReceivedBy);
591 }
592
593 /**
594 * Gets the ReceivedRepresenting property of the e-mail message.
595 *
596 * @return the received representing
597 * @throws ServiceLocalException the service local exception
598 */
599 public EmailAddress getReceivedRepresenting() throws ServiceLocalException {
600 return getPropertyBag().getObjectFromPropertyDefinition(
601 EmailMessageSchema.ReceivedRepresenting);
602 }
603 }