1 /*
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3  *
4  * Copyright (c) 1997-2017 Oracle and/or its affiliates. All rights reserved.
5  *
6  * The contents of this file are subject to the terms of either the GNU
7  * General Public License Version 2 only ("GPL") or the Common Development
8  * and Distribution License("CDDL") (collectively, the "License").  You
9  * may not use this file except in compliance with the License.  You can
10  * obtain a copy of the License at
11  * https://oss.oracle.com/licenses/CDDL+GPL-1.1
12  * or LICENSE.txt.  See the License for the specific
13  * language governing permissions and limitations under the License.
14  *
15  * When distributing the software, include this License Header Notice in each
16  * file and include the License file at LICENSE.txt.
17  *
18  * GPL Classpath Exception:
19  * Oracle designates this particular file as subject to the "Classpath"
20  * exception as provided by Oracle in the GPL Version 2 section of the License
21  * file that accompanied this code.
22  *
23  * Modifications:
24  * If applicable, add the following below the License Header, with the fields
25  * enclosed by brackets [] replaced by your own identifying information:
26  * "Portions Copyright [year] [name of copyright owner]"
27  *
28  * Contributor(s):
29  * If you wish your version of this file to be governed by only the CDDL or
30  * only the GPL Version 2, indicate your decision by adding "[Contributor]
31  * elects to include this software in this distribution under the [CDDL or GPL
32  * Version 2] license."  If you don't indicate a single choice of license, a
33  * recipient has the option to distribute your version of this file under
34  * either the CDDL, the GPL Version 2 or to extend the choice of license to
35  * its licensees as provided above.  However, if you add GPL Version 2 code
36  * and therefore, elected the GPL Version 2 license, then the option applies
37  * only if the new code is made subject to such option by the copyright
38  * holder.
39  */

40
41 package javax.mail;
42
43 import java.util.Date;
44 import java.io.*;
45 import javax.mail.search.SearchTerm;
46
47 /**
48  * This class models an email message. This is an abstract class.  
49  * Subclasses provide actual implementations. <p>
50  *
51  * Message implements the Part interface. Message contains a set of
52  * attributes and a "content". Messages within a folder also have a 
53  * set of flags that describe its state within the folder.<p>
54  *
55  * Message defines some new attributes in addition to those defined
56  * in the <code>Part</code> interface. These attributes specify meta-data
57  * for the message - i.e., addressing  and descriptive information about 
58  * the message. <p>
59  *
60  * Message objects are obtained either from a Folder or by constructing
61  * a new Message object of the appropriate subclass. Messages that have
62  * been received are normally retrieved from a folder named "INBOX". <p>
63  *
64  * A Message object obtained from a folder is just a lightweight
65  * reference to the actual message. The Message is 'lazily' filled 
66  * up (on demand) when each item is requested from the message. Note
67  * that certain folder implementations may return Message objects that
68  * are pre-filled with certain user-specified items.
69  
70  * To send a message, an appropriate subclass of Message (e.g., 
71  * MimeMessage) is instantiated, the attributes and content are 
72  * filled in, and the message is sent using the <code>Transport.send</code> 
73  * method. <p>
74  *
75  * @author John Mani
76  * @author Bill Shannon
77  * @author Max Spivak
78  * @see       javax.mail.Part
79  */

80
81 public abstract class Message implements Part {
82
83     /**
84      * The number of this message within its folder, or zero if
85      * the message was not retrieved from a folder.
86      */

87     protected int msgnum = 0;
88
89     /**
90      * True if this message has been expunged.
91      */

92     protected boolean expunged     = false;
93
94     /**
95      * The containing folder, if this message is obtained from a folder
96      */

97     protected Folder folder    = null;
98
99     /**
100      * The Session object for this Message
101      */

102     protected Session session    = null;
103
104     /**
105      * No-arg version of the constructor.
106      */

107     protected Message() { }
108
109     /**
110      * Constructor that takes a Folder and a message number. 
111      * Used by Folder implementations.
112      *
113      * @param    folder    containing folder
114      * @param    msgnum    this message's sequence number within this folder
115      */

116     protected Message(Folder folder, int msgnum) {
117     this.folder = folder;
118     this.msgnum = msgnum;
119     session = folder.store.session;
120     }
121
122     /**
123      * Constructor that takes a Session. Used for client created
124      * Message objects.
125      *
126      * @param    session    A Session object
127      */

128     protected Message(Session session) {
129     this.session = session;
130     }
131
132     /**
133      * Return the Session used when this message was created.
134      *
135      * @return        the message's Session
136      * @since        JavaMail 1.5
137      */

138     public Session getSession() {
139     return session;
140     }
141
142     /**
143      * Returns the "From" attribute. The "From" attribute contains
144      * the identity of the person(s) who wished this message to 
145      * be sent. <p>
146      * 
147      * In certain implementations, this may be different
148      * from the entity that actually sent the message. <p>
149      *
150      * This method returns <code>null</code> if this attribute
151      * is not present in this message. Returns an empty array if
152      * this attribute is present, but contains no addresses.
153      *
154      * @return          array of Address objects
155      * @exception       MessagingException for failures
156      */

157     public abstract Address[] getFrom() throws MessagingException;
158
159     /**
160      * Set the "From" attribute in this Message. The value of this
161      * attribute is obtained from the property "mail.user". If this
162      * property is absent, the system property "user.name" is used.
163      *
164      * @exception    IllegalWriteException if the underlying 
165      *            implementation does not support modification 
166      *            of existing values
167      * @exception    IllegalStateException if this message is
168      *            obtained from a READ_ONLY folder.
169      * @exception       MessagingException for other failures
170      */

171     public abstract void setFrom() throws MessagingException;
172
173     /**
174      * Set the "From" attribute in this Message.
175      *
176      * @param address   the sender
177      * @exception    IllegalWriteException if the underlying 
178      *            implementation does not support modification 
179      *            of existing values
180      * @exception    IllegalStateException if this message is
181      *            obtained from a READ_ONLY folder.
182      * @exception       MessagingException for other failures
183      */

184     public abstract void setFrom(Address address) 
185             throws MessagingException;
186
187     /**
188      * Add these addresses to the existing "From" attribute 
189      *
190      * @param addresses    the senders
191      * @exception    IllegalWriteException if the underlying 
192      *            implementation does not support modification 
193      *            of existing values
194      * @exception    IllegalStateException if this message is
195      *            obtained from a READ_ONLY folder.
196      * @exception       MessagingException for other failures
197      */

198     public abstract void addFrom(Address[] addresses) 
199             throws MessagingException;
200
201     /**
202      * This inner class defines the types of recipients allowed by
203      * the Message class. The currently defined types are TO,
204      * CC and BCC.
205      *
206      * Note that this class only has a protected constructor, thereby
207      * restricting new Recipient types to either this class or subclasses.
208      * This effectively implements an enumeration of the allowed Recipient
209      * types.
210      *
211      * The following code sample shows how to use this class to obtain
212      * the "TO" recipients from a message.
213      * <blockquote><pre>
214      *
215      * Message msg = folder.getMessages(1);
216      * Address[] a = m.getRecipients(Message.RecipientType.TO);
217      *
218      * </pre></blockquote>
219      *
220      * @see javax.mail.Message#getRecipients
221      * @see javax.mail.Message#setRecipients
222      * @see javax.mail.Message#addRecipients
223      */

224     public static class RecipientType implements Serializable {
225     /**
226      * The "To" (primary) recipients.
227      */

228     public static final RecipientType TO = new RecipientType("To");
229     /**
230      * The "Cc" (carbon copy) recipients.
231      */

232     public static final RecipientType CC = new RecipientType("Cc");
233     /**
234      * The "Bcc" (blind carbon copy) recipients.
235      */

236     public static final RecipientType BCC = new RecipientType("Bcc");
237
238     /**
239      * The type of recipient, usually the name of a corresponding
240      * Internet standard header.
241      *
242      * @serial
243      */

244     protected String type;
245
246     private static final long serialVersionUID = -7479791750606340008L;
247
248     /**
249      * Constructor for use by subclasses.
250      *
251      * @param    type    the recipient type
252      */

253     protected RecipientType(String type) {
254         this.type = type;
255     }
256
257     /**
258      * When deserializing a RecipientType, we need to make sure to
259      * return only one of the known static final instances defined
260      * in this class.  Subclasses must implement their own
261      * <code>readResolve</code> method that checks for their known
262      * instances before calling this super method.
263      *
264      * @return    the RecipientType object instance
265      * @exception    ObjectStreamException for object stream errors
266      */

267     protected Object readResolve() throws ObjectStreamException {
268         if (type.equals("To"))
269         return TO;
270         else if (type.equals("Cc"))
271         return CC;
272         else if (type.equals("Bcc"))
273         return BCC;
274         else
275         throw new InvalidObjectException(
276             "Attempt to resolve unknown RecipientType: " + type);
277     }
278
279     @Override
280     public String toString() {
281         return type;
282     }
283     }
284
285     /**
286      * Get all the recipient addresses of the given type. <p>
287      *
288      * This method returns <code>null</code> if no recipients of
289      * the given type are present in this message. It may return an 
290      * empty array if the header is present, but contains no addresses.
291      *
292      * @param type      the recipient type
293      * @return          array of Address objects
294      * @exception       MessagingException for failures
295      * @see Message.RecipientType#TO
296      * @see Message.RecipientType#CC
297      * @see Message.RecipientType#BCC
298      */

299     public abstract Address[] getRecipients(RecipientType type)
300                                 throws MessagingException;
301
302     /**
303      * Get all the recipient addresses for the message.
304      * The default implementation extracts the TO, CC, and BCC
305      * recipients using the <code>getRecipients</code> method. <p>
306      *
307      * This method returns <code>null</code> if none of the recipient
308      * headers are present in this message.  It may Return an empty array
309      * if any recipient header is present, but contains no addresses.
310      *
311      * @return          array of Address objects
312      * @exception       MessagingException for failures
313      * @see Message.RecipientType#TO
314      * @see Message.RecipientType#CC
315      * @see Message.RecipientType#BCC
316      * @see #getRecipients
317      */

318     public Address[] getAllRecipients() throws MessagingException {
319     Address[] to = getRecipients(RecipientType.TO);
320     Address[] cc = getRecipients(RecipientType.CC);
321     Address[] bcc = getRecipients(RecipientType.BCC);
322
323     if (cc == null && bcc == null)
324         return to;        // a common case
325
326     int numRecip =
327         (to != null ? to.length : 0) +
328         (cc != null ? cc.length : 0) +
329         (bcc != null ? bcc.length : 0);
330     Address[] addresses = new Address[numRecip];
331     int pos = 0;
332     if (to != null) {
333         System.arraycopy(to, 0, addresses, pos, to.length);
334         pos += to.length;
335     }
336     if (cc != null) {
337         System.arraycopy(cc, 0, addresses, pos, cc.length);
338         pos += cc.length;
339     }
340     if (bcc != null) {
341         System.arraycopy(bcc, 0, addresses, pos, bcc.length);
342         // pos += bcc.length;
343     }
344     return addresses;
345     }
346
347     /**
348      * Set the recipient addresses.  All addresses of the specified
349      * type are replaced by the addresses parameter.
350      *
351      * @param type      the recipient type
352      * @param addresses the addresses
353      * @exception    IllegalWriteException if the underlying 
354      *            implementation does not support modification 
355      *            of existing values
356      * @exception    IllegalStateException if this message is
357      *            obtained from a READ_ONLY folder.
358      * @exception       MessagingException for other failures
359      */

360     public abstract void setRecipients(RecipientType type, Address[] addresses)
361                                 throws MessagingException;
362
363     /**
364      * Set the recipient address.  All addresses of the specified
365      * type are replaced by the address parameter. <p>
366      *
367      * The default implementation uses the <code>setRecipients</code> method.
368      *
369      * @param type      the recipient type
370      * @param address    the address
371      * @exception    IllegalWriteException if the underlying 
372      *            implementation does not support modification 
373      *            of existing values
374      * @exception       MessagingException for other failures
375      */

376     public void setRecipient(RecipientType type, Address address)
377                                 throws MessagingException {
378     if (address == null)
379         setRecipients(type, null);
380     else {
381         Address[] a = new Address[1];
382         a[0] = address;
383         setRecipients(type, a);
384     }
385     }
386
387     /**
388      * Add these recipient addresses to the existing ones of the given type.
389      *
390      * @param type      the recipient type
391      * @param addresses the addresses
392      * @exception    IllegalWriteException if the underlying 
393      *            implementation does not support modification 
394      *            of existing values
395      * @exception    IllegalStateException if this message is
396      *            obtained from a READ_ONLY folder.
397      * @exception       MessagingException for other failures
398      */

399     public abstract void addRecipients(RecipientType type, Address[] addresses)
400                                 throws MessagingException;
401
402     /**
403      * Add this recipient address to the existing ones of the given type. <p>
404      *
405      * The default implementation uses the <code>addRecipients</code> method.
406      *
407      * @param type      the recipient type
408      * @param address    the address
409      * @exception    IllegalWriteException if the underlying 
410      *            implementation does not support modification 
411      *            of existing values
412      * @exception       MessagingException for other failures
413      */

414     public void addRecipient(RecipientType type, Address address)
415                                 throws MessagingException {
416     Address[] a = new Address[1];
417     a[0] = address;
418     addRecipients(type, a);
419     }
420
421     /**
422      * Get the addresses to which replies should be directed.
423      * This will usually be the sender of the message, but
424      * some messages may direct replies to a different address. <p>
425      *
426      * The default implementation simply calls the <code>getFrom</code>
427      * method. <p>
428      *
429      * This method returns <code>null</code> if the corresponding
430      * header is not present. Returns an empty array if the header
431      * is present, but contains no addresses.
432      *
433      * @return          addresses to which replies should be directed
434      * @exception       MessagingException for failures
435      * @see        #getFrom
436      */

437     public Address[] getReplyTo() throws MessagingException {
438         return getFrom();
439     }
440
441     /**
442      * Set the addresses to which replies should be directed.
443      * (Normally only a single address will be specified.)
444      * Not all message types allow this to be specified separately
445      * from the sender of the message. <p>
446      *
447      * The default implementation provided here just throws the
448      * MethodNotSupportedException.
449      *
450      * @param addresses addresses to which replies should be directed
451      * @exception    IllegalWriteException if the underlying 
452      *            implementation does not support modification 
453      *            of existing values
454      * @exception    IllegalStateException if this message is
455      *            obtained from a READ_ONLY folder.
456      * @exception    MethodNotSupportedException if the underlying 
457      *            implementation does not support setting this
458      *            attribute
459      * @exception       MessagingException for other failures
460      */

461     public void setReplyTo(Address[] addresses) throws MessagingException {
462     throw new MethodNotSupportedException("setReplyTo not supported");
463     }
464
465     /**
466      * Get the subject of this message.
467      *
468      * @return          the subject
469      * @exception       MessagingException for failures
470      */

471     public abstract String getSubject() throws MessagingException;
472
473     /**
474      * Set the subject of this message.
475      *
476      * @param subject   the subject
477      * @exception    IllegalWriteException if the underlying 
478      *            implementation does not support modification 
479      *            of existing values
480      * @exception    IllegalStateException if this message is
481      *            obtained from a READ_ONLY folder.
482      * @exception       MessagingException for other failures
483      */

484     public abstract void setSubject(String subject) 
485             throws MessagingException;
486
487     /**
488      * Get the date this message was sent.
489      *
490      * @return          the date this message was sent
491      * @exception       MessagingException for failures
492      */

493     public abstract Date getSentDate() throws MessagingException;
494
495     /**
496      * Set the sent date of this message.
497      *
498      * @param date      the sent date of this message
499      * @exception    IllegalWriteException if the underlying 
500      *            implementation does not support modification 
501      *            of existing values
502      * @exception    IllegalStateException if this message is
503      *            obtained from a READ_ONLY folder.
504      * @exception       MessagingException for other failures
505      */

506     public abstract void setSentDate(Date date) throws MessagingException;
507
508     /**
509      * Get the date this message was received.
510      *
511      * @return          the date this message was received
512      * @exception       MessagingException for failures
513      */

514     public abstract Date getReceivedDate() throws MessagingException;
515
516     /**
517      * Returns a <code>Flags</code> object containing the flags for 
518      * this message. <p>
519      *
520      * Modifying any of the flags in this returned Flags object will 
521      * not affect the flags of this message. Use <code>setFlags()</code>
522      * to do that. <p>
523      *
524      * @return        Flags object containing the flags for this message
525      * @see         javax.mail.Flags
526      * @see         #setFlags
527      * @exception       MessagingException for failures
528      */

529     public abstract Flags getFlags() throws MessagingException;
530
531     /**
532      * Check whether the flag specified in the <code>flag</code>
533      * argument is set in this message. <p>
534      *
535      * The default implementation uses <code>getFlags</code>.
536      *
537      * @param flag    the flag
538      * @return        value of the specified flag for this message
539      * @see         javax.mail.Flags.Flag
540      * @see        javax.mail.Flags.Flag#ANSWERED
541      * @see        javax.mail.Flags.Flag#DELETED
542      * @see        javax.mail.Flags.Flag#DRAFT
543      * @see        javax.mail.Flags.Flag#FLAGGED
544      * @see        javax.mail.Flags.Flag#RECENT
545      * @see        javax.mail.Flags.Flag#SEEN
546      * @exception       MessagingException for failures
547      */

548     public boolean isSet(Flags.Flag flag) throws MessagingException {
549     return getFlags().contains(flag);
550     }
551
552     /**
553      * Set the specified flags on this message to the specified value.
554      * Note that any flags in this message that are not specified in
555      * the given <code>Flags</code> object are unaffected. <p>
556      *
557      * This will result in a <code>MessageChangedEvent</code> being 
558      * delivered to any MessageChangedListener registered on this 
559      * Message's containing folder.
560      *
561      * @param flag    Flags object containing the flags to be set
562      * @param set    the value to be set
563      * @exception    IllegalWriteException if the underlying 
564      *            implementation does not support modification 
565      *            of existing values.
566      * @exception    IllegalStateException if this message is
567      *            obtained from a READ_ONLY folder.
568      * @exception       MessagingException for other failures
569      * @see        javax.mail.event.MessageChangedEvent
570      */

571     public abstract void setFlags(Flags flag, boolean set)
572                 throws MessagingException;
573
574     /**
575      * Set the specified flag on this message to the specified value.
576      *
577      * This will result in a <code>MessageChangedEvent</code> being 
578      * delivered to any MessageChangedListener registered on this 
579      * Message's containing folder. <p>
580      *
581      * The default implementation uses the <code>setFlags</code> method.
582      *
583      * @param flag    Flags.Flag object containing the flag to be set
584      * @param set    the value to be set
585      * @exception    IllegalWriteException if the underlying 
586      *            implementation does not support modification 
587      *            of existing values.
588      * @exception    IllegalStateException if this message is
589      *            obtained from a READ_ONLY folder.
590      * @exception       MessagingException for other failures
591      * @see        javax.mail.event.MessageChangedEvent
592      */

593     public void setFlag(Flags.Flag flag, boolean set)
594                 throws MessagingException {
595     Flags f = new Flags(flag);
596     setFlags(f, set);
597     }
598
599     /**
600      * Get the Message number for this Message.
601      * A Message object's message number is the relative
602      * position of this Message in its Folder. Note that the message
603      * number for a particular Message can change during a session
604      * if other messages in the Folder are deleted and expunged. <p>
605      *
606      * Valid message numbers start at 1. Messages that do not belong
607      * to any folder (like newly composed or derived messages) have 0
608      * as their message number.
609      *
610      * @return    the message number
611      */

612     public int getMessageNumber() {
613     return msgnum;
614     }
615
616     /**
617      * Set the Message number for this Message. This method is
618      * invoked only by the implementation classes.
619      *
620      * @param    msgnum    the message number
621      */

622     protected void setMessageNumber(int msgnum) {
623     this.msgnum = msgnum;
624     }
625
626     /**
627      * Get the folder from which this message was obtained. If
628      * this is a new message or nested message, this method returns
629      * null.
630      *
631      * @return    the containing folder
632      */

633     public Folder getFolder() {
634     return folder;
635     }
636
637     /**
638      * Checks whether this message is expunged. All other methods except
639      * <code>getMessageNumber()</code> are invalid on an expunged 
640      * Message object. <p>
641      *
642      * Messages that are expunged due to an explict <code>expunge()</code>
643      * request on the containing Folder are removed from the Folder 
644      * immediately. Messages that are externally expunged by another source
645      * are marked "expunged" and return true for the isExpunged() method, 
646      * but they are not removed from the Folder until an explicit 
647      * <code>expunge()</code> is done on the Folder. <p>
648      * 
649      * See the description of <code>expunge()</code> for more details on
650      * expunge handling.
651      *
652      * @return    true if the message is expunged
653      * @see    Folder#expunge
654      */

655     public boolean isExpunged() {
656     return expunged;
657     }
658
659     /**
660      * Sets the expunged flag for this Message. This method is to
661      * be used only by the implementation classes.
662      *
663      * @param expunged    the expunged flag
664      */

665     protected void setExpunged(boolean expunged) {
666     this.expunged = expunged;
667     }
668
669     /**
670      * Get a new Message suitable for a reply to this message.
671      * The new Message will have its attributes and headers 
672      * set up appropriately.  Note that this new message object
673      * will be empty, that is, it will <strong>not</strong> have a "content".
674      * These will have to be suitably filled in by the client. <p>
675      *
676      * If <code>replyToAll</code> is set, the new Message will be addressed
677      * to all recipients of this message.  Otherwise, the reply will be
678      * addressed to only the sender of this message (using the value
679      * of the <code>getReplyTo</code> method).  <p>
680      *
681      * The "Subject" field is filled in with the original subject
682      * prefixed with "Re:" (unless it already starts with "Re:"). <p>
683      *
684      * The reply message will use the same session as this message.
685      *
686      * @param    replyToAll    reply should be sent to all recipients
687      *                of this message
688      * @return        the reply Message
689      * @exception    MessagingException for failures
690      */

691     public abstract Message reply(boolean replyToAll) throws MessagingException;
692
693     /**
694      * Save any changes made to this message into the message-store
695      * when the containing folder is closed, if the message is contained
696      * in a folder.  (Some implementations may save the changes
697      * immediately.)  Update any header fields to be consistent with the
698      * changed message contents.  If any part of a message's headers or
699      * contents are changed, saveChanges must be called to ensure that
700      * those changes are permanent.  If saveChanges is not called, any
701      * such modifications may or may not be saved, depending on the
702      * message store and folder implementation. <p>
703      *
704      * Messages obtained from folders opened READ_ONLY should not be
705      * modified and saveChanges should not be called on such messages.
706      *
707      * @exception    IllegalStateException if this message is
708      *            obtained from a READ_ONLY folder.
709      * @exception    IllegalWriteException if the underlying 
710      *            implementation does not support modification 
711      *            of existing values.
712      * @exception       MessagingException for other failures
713      */

714     public abstract void saveChanges() throws MessagingException;
715
716     /**
717      * Apply the specified Search criterion to this message.
718      *
719      * @param term    the Search criterion
720      * @return        true if the Message matches this search
721      *            criterion, false otherwise.
722      * @exception       MessagingException for failures
723      * @see        javax.mail.search.SearchTerm
724      */

725     public boolean match(SearchTerm term) throws MessagingException {
726     return term.match(this);
727     }
728 }
729