001/**************************************************************** 002 * Licensed to the Apache Software Foundation (ASF) under one * 003 * or more contributor license agreements. See the NOTICE file * 004 * distributed with this work for additional information * 005 * regarding copyright ownership. The ASF licenses this file * 006 * to you under the Apache License, Version 2.0 (the * 007 * "License"); you may not use this file except in compliance * 008 * with the License. You may obtain a copy of the License at * 009 * * 010 * http://www.apache.org/licenses/LICENSE-2.0 * 011 * * 012 * Unless required by applicable law or agreed to in writing, * 013 * software distributed under the License is distributed on an * 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 015 * KIND, either express or implied. See the License for the * 016 * specific language governing permissions and limitations * 017 * under the License. * 018 ****************************************************************/ 019 020package org.apache.james.mime4j.message; 021 022import java.util.Arrays; 023import java.util.Collection; 024import java.util.Collections; 025import java.util.Date; 026import java.util.TimeZone; 027 028import org.apache.james.mime4j.dom.Header; 029import org.apache.james.mime4j.dom.Message; 030import org.apache.james.mime4j.dom.address.Address; 031import org.apache.james.mime4j.dom.address.AddressList; 032import org.apache.james.mime4j.dom.address.Mailbox; 033import org.apache.james.mime4j.dom.address.MailboxList; 034import org.apache.james.mime4j.dom.field.AddressListField; 035import org.apache.james.mime4j.dom.field.DateTimeField; 036import org.apache.james.mime4j.dom.field.FieldName; 037import org.apache.james.mime4j.dom.field.MailboxField; 038import org.apache.james.mime4j.dom.field.MailboxListField; 039import org.apache.james.mime4j.dom.field.ParsedField; 040import org.apache.james.mime4j.dom.field.UnstructuredField; 041import org.apache.james.mime4j.stream.Field; 042 043/** 044 * Abstract MIME message. 045 */ 046public abstract class AbstractMessage extends AbstractEntity implements Message { 047 048 /** 049 * Returns the value of the <i>Message-ID</i> header field of this message 050 * or <code>null</code> if it is not present. 051 * 052 * @return the identifier of this message. 053 */ 054 public String getMessageId() { 055 Field field = obtainField(FieldName.MESSAGE_ID); 056 if (field == null) 057 return null; 058 059 return field.getBody(); 060 } 061 062 /** 063 * Creates and sets a new <i>Message-ID</i> header field for this message. 064 * A <code>Header</code> is created if this message does not already have 065 * one. 066 * 067 * @param hostname 068 * host name to be included in the identifier or 069 * <code>null</code> if no host name should be included. 070 */ 071 public void createMessageId(String hostname) { 072 Header header = obtainHeader(); 073 074 header.setField(newMessageId(hostname)); 075 } 076 077 protected abstract ParsedField newMessageId(String hostname); 078 079 /** 080 * Returns the (decoded) value of the <i>Subject</i> header field of this 081 * message or <code>null</code> if it is not present. 082 * 083 * @return the subject of this message. 084 */ 085 public String getSubject() { 086 UnstructuredField field = obtainField(FieldName.SUBJECT); 087 if (field == null) 088 return null; 089 090 return field.getValue(); 091 } 092 093 /** 094 * Sets the <i>Subject</i> header field for this message. The specified 095 * string may contain non-ASCII characters, in which case it gets encoded as 096 * an 'encoded-word' automatically. A <code>Header</code> is created if 097 * this message does not already have one. 098 * 099 * @param subject 100 * subject to set or <code>null</code> to remove the subject 101 * header field. 102 */ 103 public void setSubject(String subject) { 104 Header header = obtainHeader(); 105 106 if (subject == null) { 107 header.removeFields(FieldName.SUBJECT); 108 } else { 109 header.setField(newSubject(subject)); 110 } 111 } 112 113 /** 114 * Returns the value of the <i>Date</i> header field of this message as 115 * <code>Date</code> object or <code>null</code> if it is not present. 116 * 117 * @return the date of this message. 118 */ 119 public Date getDate() { 120 DateTimeField dateField = obtainField(FieldName.DATE); 121 if (dateField == null) 122 return null; 123 124 return dateField.getDate(); 125 } 126 127 /** 128 * Sets the <i>Date</i> header field for this message. This method uses the 129 * default <code>TimeZone</code> of this host to encode the specified 130 * <code>Date</code> object into a string. 131 * 132 * @param date 133 * date to set or <code>null</code> to remove the date header 134 * field. 135 */ 136 public void setDate(Date date) { 137 setDate(date, null); 138 } 139 140 /** 141 * Sets the <i>Date</i> header field for this message. The specified 142 * <code>TimeZone</code> is used to encode the specified <code>Date</code> 143 * object into a string. 144 * 145 * @param date 146 * date to set or <code>null</code> to remove the date header 147 * field. 148 * @param zone 149 * a time zone. 150 */ 151 public void setDate(Date date, TimeZone zone) { 152 Header header = obtainHeader(); 153 154 if (date == null) { 155 header.removeFields(FieldName.DATE); 156 } else { 157 header.setField(newDate(date, zone)); 158 } 159 } 160 161 /** 162 * Returns the value of the <i>Sender</i> header field of this message as 163 * <code>Mailbox</code> object or <code>null</code> if it is not 164 * present. 165 * 166 * @return the sender of this message. 167 */ 168 public Mailbox getSender() { 169 return getMailbox(FieldName.SENDER); 170 } 171 172 /** 173 * Sets the <i>Sender</i> header field of this message to the specified 174 * mailbox address. 175 * 176 * @param sender 177 * address to set or <code>null</code> to remove the header 178 * field. 179 */ 180 public void setSender(Mailbox sender) { 181 setMailbox(FieldName.SENDER, sender); 182 } 183 184 /** 185 * Returns the value of the <i>From</i> header field of this message as 186 * <code>MailboxList</code> object or <code>null</code> if it is not 187 * present. 188 * 189 * @return value of the from field of this message. 190 */ 191 public MailboxList getFrom() { 192 return getMailboxList(FieldName.FROM); 193 } 194 195 /** 196 * Sets the <i>From</i> header field of this message to the specified 197 * mailbox address. 198 * 199 * @param from 200 * address to set or <code>null</code> to remove the header 201 * field. 202 */ 203 public void setFrom(Mailbox from) { 204 setMailboxList(FieldName.FROM, from); 205 } 206 207 /** 208 * Sets the <i>From</i> header field of this message to the specified 209 * mailbox addresses. 210 * 211 * @param from 212 * addresses to set or <code>null</code> or no arguments to 213 * remove the header field. 214 */ 215 public void setFrom(Mailbox... from) { 216 setMailboxList(FieldName.FROM, from); 217 } 218 219 /** 220 * Sets the <i>From</i> header field of this message to the specified 221 * mailbox addresses. 222 * 223 * @param from 224 * addresses to set or <code>null</code> or an empty collection 225 * to remove the header field. 226 */ 227 public void setFrom(Collection<Mailbox> from) { 228 setMailboxList(FieldName.FROM, from); 229 } 230 231 /** 232 * Returns the value of the <i>To</i> header field of this message as 233 * <code>AddressList</code> object or <code>null</code> if it is not 234 * present. 235 * 236 * @return value of the to field of this message. 237 */ 238 public AddressList getTo() { 239 return getAddressList(FieldName.TO); 240 } 241 242 /** 243 * Sets the <i>To</i> header field of this message to the specified 244 * address. 245 * 246 * @param to 247 * address to set or <code>null</code> to remove the header 248 * field. 249 */ 250 public void setTo(Address to) { 251 setAddressList(FieldName.TO, to); 252 } 253 254 /** 255 * Sets the <i>To</i> header field of this message to the specified 256 * addresses. 257 * 258 * @param to 259 * addresses to set or <code>null</code> or no arguments to 260 * remove the header field. 261 */ 262 public void setTo(Address... to) { 263 setAddressList(FieldName.TO, to); 264 } 265 266 /** 267 * Sets the <i>To</i> header field of this message to the specified 268 * addresses. 269 * 270 * @param to 271 * addresses to set or <code>null</code> or an empty collection 272 * to remove the header field. 273 */ 274 public void setTo(Collection<? extends Address> to) { 275 setAddressList(FieldName.TO, to); 276 } 277 278 /** 279 * Returns the value of the <i>Cc</i> header field of this message as 280 * <code>AddressList</code> object or <code>null</code> if it is not 281 * present. 282 * 283 * @return value of the cc field of this message. 284 */ 285 public AddressList getCc() { 286 return getAddressList(FieldName.CC); 287 } 288 289 /** 290 * Sets the <i>Cc</i> header field of this message to the specified 291 * address. 292 * 293 * @param cc 294 * address to set or <code>null</code> to remove the header 295 * field. 296 */ 297 public void setCc(Address cc) { 298 setAddressList(FieldName.CC, cc); 299 } 300 301 /** 302 * Sets the <i>Cc</i> header field of this message to the specified 303 * addresses. 304 * 305 * @param cc 306 * addresses to set or <code>null</code> or no arguments to 307 * remove the header field. 308 */ 309 public void setCc(Address... cc) { 310 setAddressList(FieldName.CC, cc); 311 } 312 313 /** 314 * Sets the <i>Cc</i> header field of this message to the specified 315 * addresses. 316 * 317 * @param cc 318 * addresses to set or <code>null</code> or an empty collection 319 * to remove the header field. 320 */ 321 public void setCc(Collection<? extends Address> cc) { 322 setAddressList(FieldName.CC, cc); 323 } 324 325 /** 326 * Returns the value of the <i>Bcc</i> header field of this message as 327 * <code>AddressList</code> object or <code>null</code> if it is not 328 * present. 329 * 330 * @return value of the bcc field of this message. 331 */ 332 public AddressList getBcc() { 333 return getAddressList(FieldName.BCC); 334 } 335 336 /** 337 * Sets the <i>Bcc</i> header field of this message to the specified 338 * address. 339 * 340 * @param bcc 341 * address to set or <code>null</code> to remove the header 342 * field. 343 */ 344 public void setBcc(Address bcc) { 345 setAddressList(FieldName.BCC, bcc); 346 } 347 348 /** 349 * Sets the <i>Bcc</i> header field of this message to the specified 350 * addresses. 351 * 352 * @param bcc 353 * addresses to set or <code>null</code> or no arguments to 354 * remove the header field. 355 */ 356 public void setBcc(Address... bcc) { 357 setAddressList(FieldName.BCC, bcc); 358 } 359 360 /** 361 * Sets the <i>Bcc</i> header field of this message to the specified 362 * addresses. 363 * 364 * @param bcc 365 * addresses to set or <code>null</code> or an empty collection 366 * to remove the header field. 367 */ 368 public void setBcc(Collection<? extends Address> bcc) { 369 setAddressList(FieldName.BCC, bcc); 370 } 371 372 /** 373 * Returns the value of the <i>Reply-To</i> header field of this message as 374 * <code>AddressList</code> object or <code>null</code> if it is not 375 * present. 376 * 377 * @return value of the reply to field of this message. 378 */ 379 public AddressList getReplyTo() { 380 return getAddressList(FieldName.REPLY_TO); 381 } 382 383 /** 384 * Sets the <i>Reply-To</i> header field of this message to the specified 385 * address. 386 * 387 * @param replyTo 388 * address to set or <code>null</code> to remove the header 389 * field. 390 */ 391 public void setReplyTo(Address replyTo) { 392 setAddressList(FieldName.REPLY_TO, replyTo); 393 } 394 395 /** 396 * Sets the <i>Reply-To</i> header field of this message to the specified 397 * addresses. 398 * 399 * @param replyTo 400 * addresses to set or <code>null</code> or no arguments to 401 * remove the header field. 402 */ 403 public void setReplyTo(Address... replyTo) { 404 setAddressList(FieldName.REPLY_TO, replyTo); 405 } 406 407 /** 408 * Sets the <i>Reply-To</i> header field of this message to the specified 409 * addresses. 410 * 411 * @param replyTo 412 * addresses to set or <code>null</code> or an empty collection 413 * to remove the header field. 414 */ 415 public void setReplyTo(Collection<? extends Address> replyTo) { 416 setAddressList(FieldName.REPLY_TO, replyTo); 417 } 418 419 private Mailbox getMailbox(String fieldName) { 420 MailboxField field = obtainField(fieldName); 421 if (field == null) 422 return null; 423 424 return field.getMailbox(); 425 } 426 427 private void setMailbox(String fieldName, Mailbox mailbox) { 428 Header header = obtainHeader(); 429 430 if (mailbox == null) { 431 header.removeFields(fieldName); 432 } else { 433 header.setField(newMailbox(fieldName, mailbox)); 434 } 435 } 436 437 private MailboxList getMailboxList(String fieldName) { 438 MailboxListField field = obtainField(fieldName); 439 if (field == null) 440 return null; 441 442 return field.getMailboxList(); 443 } 444 445 private void setMailboxList(String fieldName, Mailbox mailbox) { 446 setMailboxList(fieldName, mailbox == null ? null : Collections 447 .singleton(mailbox)); 448 } 449 450 private void setMailboxList(String fieldName, Mailbox... mailboxes) { 451 setMailboxList(fieldName, mailboxes == null ? null : Arrays 452 .asList(mailboxes)); 453 } 454 455 private void setMailboxList(String fieldName, Collection<Mailbox> mailboxes) { 456 Header header = obtainHeader(); 457 458 if (mailboxes == null || mailboxes.isEmpty()) { 459 header.removeFields(fieldName); 460 } else { 461 header.setField(newMailboxList(fieldName, mailboxes)); 462 } 463 } 464 465 private AddressList getAddressList(String fieldName) { 466 AddressListField field = obtainField(fieldName); 467 if (field == null) 468 return null; 469 470 return field.getAddressList(); 471 } 472 473 private void setAddressList(String fieldName, Address address) { 474 setAddressList(fieldName, address == null ? null : Collections 475 .singleton(address)); 476 } 477 478 private void setAddressList(String fieldName, Address... addresses) { 479 setAddressList(fieldName, addresses == null ? null : Arrays 480 .asList(addresses)); 481 } 482 483 private void setAddressList(String fieldName, Collection<? extends Address> addresses) { 484 Header header = obtainHeader(); 485 486 if (addresses == null || addresses.isEmpty()) { 487 header.removeFields(fieldName); 488 } else { 489 header.setField(newAddressList(fieldName, addresses)); 490 } 491 } 492 493 protected abstract AddressListField newAddressList(String fieldName, Collection<? extends Address> addresses); 494 495 protected abstract UnstructuredField newSubject(String subject); 496 497 protected abstract DateTimeField newDate(Date date, TimeZone zone); 498 499 protected abstract MailboxField newMailbox(String fieldName, Mailbox mailbox); 500 501 protected abstract MailboxListField newMailboxList(String fieldName, Collection<Mailbox> mailboxes); 502 503 504}