001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package org.apache.commons.net.smtp;
019
020import java.text.SimpleDateFormat;
021import java.util.Date;
022import java.util.Locale;
023
024/**
025 * This class is used to construct a bare minimum acceptable header for an email message. To construct more complicated headers you should refer to RFC 5322.
026 * When the Java Mail API is finalized, you will be able to use it to compose fully compliant Internet text messages.
027 * <p>
028 * The main purpose of the class is to faciliatate the mail sending process, by relieving the programmer from having to explicitly format a simple message
029 * header. For example:
030 *
031 * <pre>
032 * writer = client.sendMessageData();
033 * if(writer == null) // failure
034 *   return false;
035 * header =
036 *    new SimpleSMTPHeader("foobar@foo.com", "foo@bar.com" "Just testing");
037 * header.addCC("bar@foo.com");
038 * header.addHeaderField("Organization", "Foobar, Inc.");
039 * writer.write(header.toString());
040 * writer.write("This is just a test");
041 * writer.close();
042 * if(!client.completePendingCommand()) // failure
043 *   return false;
044 * </pre>
045 *
046 * @see SMTPClient
047 */
048
049public class SimpleSMTPHeader {
050    private final String subject;
051    private final String from;
052    private final String to;
053    private final StringBuffer headerFields;
054    private boolean hasHeaderDate;
055    private StringBuffer cc;
056
057    /**
058     * Creates a new SimpleSMTPHeader instance initialized with the given from, to, and subject header field values.
059     * <p>
060     *
061     * @param from    The value of the <code>From:</code> header field. This should be the sender's email address. Must not be null.
062     * @param to      The value of the <code>To:</code> header field. This should be the recipient's email address. May be null
063     * @param subject The value of the <code>Subject:</code> header field. This should be the subject of the message. May be null
064     */
065    public SimpleSMTPHeader(final String from, final String to, final String subject) {
066        if (from == null) {
067            throw new IllegalArgumentException("From cannot be null");
068        }
069        this.to = to;
070        this.from = from;
071        this.subject = subject;
072        this.headerFields = new StringBuffer();
073        this.cc = null;
074    }
075
076    /**
077     * Add an email address to the CC (carbon copy or courtesy copy) list.
078     * <p>
079     *
080     * @param address The email address to add to the CC list.
081     */
082    public void addCC(final String address) {
083        if (cc == null) {
084            cc = new StringBuffer();
085        } else {
086            cc.append(", ");
087        }
088
089        cc.append(address);
090    }
091
092    /**
093     * Adds an arbitrary header field with the given value to the article header. These headers will be written before the From, To, Subject, and Cc fields when
094     * the SimpleSMTPHeader is convertered to a string. An example use would be:
095     *
096     * <pre>
097     * header.addHeaderField("Organization", "Foobar, Inc.");
098     * </pre>
099     * <p>
100     *
101     * @param headerField The header field to add, not including the colon.
102     * @param value       The value of the added header field.
103     */
104    public void addHeaderField(final String headerField, final String value) {
105        if (!hasHeaderDate && "Date".equals(headerField)) {
106            hasHeaderDate = true;
107        }
108        headerFields.append(headerField);
109        headerFields.append(": ");
110        headerFields.append(value);
111        headerFields.append('\n');
112    }
113
114    /**
115     * Converts the SimpleSMTPHeader to a properly formatted header in the form of a String, including the blank line used to separate the header from the
116     * article body. The header fields CC and Subject are only included when they are non-null.
117     * <p>
118     *
119     * @return The message header in the form of a String.
120     */
121    @Override
122    public String toString() {
123        final StringBuilder header = new StringBuilder();
124
125        final String pattern = "EEE, dd MMM yyyy HH:mm:ss Z"; // Fri, 21 Nov 1997 09:55:06 -0600
126        final SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.ENGLISH);
127
128        if (!hasHeaderDate) {
129            addHeaderField("Date", format.format(new Date()));
130        }
131        if (headerFields.length() > 0) {
132            header.append(headerFields.toString());
133        }
134
135        header.append("From: ").append(from).append("\n");
136
137        if (to != null) {
138            header.append("To: ").append(to).append("\n");
139        }
140
141        if (cc != null) {
142            header.append("Cc: ").append(cc.toString()).append("\n");
143        }
144
145        if (subject != null) {
146            header.append("Subject: ").append(subject).append("\n");
147        }
148
149        header.append('\n'); // end of headers; body follows
150
151        return header.toString();
152    }
153}