org.apache.roller.weblogger.util.MailUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.roller.weblogger.util.MailUtil.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  The ASF licenses this file to You
 * under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.  For additional information regarding
 * copyright in this work, please see the NOTICE file in the top level
 * directory of this distribution.
 */

package org.apache.roller.weblogger.util;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.TreeSet;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.SendFailedException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.Address;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.roller.weblogger.WebloggerException;
import org.apache.roller.weblogger.business.MailProvider;
import org.apache.roller.weblogger.business.WebloggerFactory;
import org.apache.roller.weblogger.business.UserManager;
import org.apache.roller.weblogger.business.WeblogManager;
import org.apache.roller.weblogger.business.startup.WebloggerStartup;
import org.apache.roller.weblogger.config.WebloggerConfig;
import org.apache.roller.weblogger.config.WebloggerRuntimeConfig;
import org.apache.roller.weblogger.pojos.User;
import org.apache.roller.weblogger.pojos.WeblogEntry;
import org.apache.roller.weblogger.pojos.Weblog;
import org.apache.roller.weblogger.pojos.WeblogEntryComment;
import org.apache.roller.weblogger.pojos.WeblogPermission;
import org.apache.roller.weblogger.util.RollerMessages.RollerMessage;

/**
 * A utility class for helping with sending emails.
 */
public class MailUtil {

    private static Log log = LogFactory.getLog(MailUtil.class);

    private static final String EMAIL_ADDR_REGEXP = "^.*@.*[.].{2,}$";

    /**
     * Ideally mail senders should call this first to avoid errors that occur 
     * when mail is not properly configured. We'll complain about that at 
     * startup, no need to complain on every attempt to send.
     */
    public static boolean isMailConfigured() {
        return WebloggerStartup.getMailProvider() != null;
    }

    /**
     * Send an email notice that a new pending entry has been submitted.
     */
    public static void sendPendingEntryNotice(WeblogEntry entry) throws WebloggerException {

        Session mailSession = WebloggerStartup.getMailProvider() != null
                ? WebloggerStartup.getMailProvider().getSession()
                : null;

        if (mailSession == null) {
            throw new WebloggerException("Couldn't get mail Session");
        }

        try {
            UserManager umgr = WebloggerFactory.getWeblogger().getUserManager();
            WeblogManager wmgr = WebloggerFactory.getWeblogger().getWeblogManager();

            String userName = entry.getCreator().getUserName();
            String from = entry.getCreator().getEmailAddress();
            String cc[] = new String[] { from };
            String bcc[] = new String[0];
            String to[];
            String subject;
            String content;

            // list of enabled website authors and admins
            ArrayList reviewers = new ArrayList();
            List websiteUsers = wmgr.getWeblogUsers(entry.getWebsite(), true);

            // build list of reviewers (website users with author permission)
            Iterator websiteUserIter = websiteUsers.iterator();
            while (websiteUserIter.hasNext()) {
                User websiteUser = (User) websiteUserIter.next();
                if (entry.getWebsite().hasUserPermission(websiteUser, WeblogPermission.POST)
                        && websiteUser.getEmailAddress() != null) {
                    reviewers.add(websiteUser.getEmailAddress());
                }
            }
            to = (String[]) reviewers.toArray(new String[reviewers.size()]);

            // Figure URL to entry edit page
            String editURL = WebloggerFactory.getWeblogger().getUrlStrategy()
                    .getEntryEditURL(entry.getWebsite().getHandle(), entry.getId(), true);

            ResourceBundle resources = ResourceBundle.getBundle("ApplicationResources",
                    entry.getWebsite().getLocaleInstance());
            StringBuffer sb = new StringBuffer();
            sb.append(MessageFormat.format(resources.getString("weblogEntry.pendingEntrySubject"),
                    new Object[] { entry.getWebsite().getName(), entry.getWebsite().getHandle() }));
            subject = sb.toString();
            sb = new StringBuffer();
            sb.append(MessageFormat.format(resources.getString("weblogEntry.pendingEntryContent"),
                    new Object[] { userName, userName, editURL }));
            content = sb.toString();
            MailUtil.sendTextMessage(from, to, cc, bcc, subject, content);
        } catch (MessagingException e) {
            log.error("ERROR: Problem sending pending entry notification email.");
        }
    }

    /**
     * Send a weblog invitation email.
     */
    public static void sendWeblogInvitation(Weblog website, User user) throws WebloggerException {

        Session mailSession = WebloggerStartup.getMailProvider() != null
                ? WebloggerStartup.getMailProvider().getSession()
                : null;

        if (mailSession == null) {
            throw new WebloggerException(
                    "ERROR: Notification email(s) not sent, " + "Roller's mail session not properly configured");
        }

        try {
            UserManager umgr = WebloggerFactory.getWeblogger().getUserManager();

            String userName = user.getUserName();
            String from = website.getEmailAddress();
            String cc[] = new String[] { from };
            String bcc[] = new String[0];
            String to[] = new String[] { user.getEmailAddress() };
            String subject;
            String content;

            // Figure URL to entry edit page
            String rootURL = WebloggerRuntimeConfig.getAbsoluteContextURL();
            String url = rootURL + "/roller-ui/menu.rol";

            ResourceBundle resources = ResourceBundle.getBundle("ApplicationResources",
                    website.getLocaleInstance());
            StringBuffer sb = new StringBuffer();
            sb.append(MessageFormat.format(resources.getString("inviteMember.notificationSubject"),
                    new Object[] { website.getName(), website.getHandle() }));
            subject = sb.toString();
            sb = new StringBuffer();
            sb.append(MessageFormat.format(resources.getString("inviteMember.notificationContent"),
                    new Object[] { website.getName(), website.getHandle(), user.getUserName(), url }));
            content = sb.toString();
            MailUtil.sendTextMessage(from, to, cc, bcc, subject, content);
        } catch (MessagingException e) {
            throw new WebloggerException("ERROR: Notification email(s) not sent, "
                    + "due to Roller configuration or mail server problem.", e);
        }
    }

    /**
     * Send a weblog invitation email.
     */
    public static void sendUserActivationEmail(User user) throws WebloggerException {

        Session mailSession = WebloggerStartup.getMailProvider() != null
                ? WebloggerStartup.getMailProvider().getSession()
                : null;

        if (mailSession == null) {
            throw new WebloggerException(
                    "ERROR: Notification email(s) not sent, " + "Roller's mail session not properly configured");
        }

        try {
            ResourceBundle resources = ResourceBundle.getBundle("ApplicationResources",
                    I18nUtils.toLocale(user.getLocale()));

            String from = WebloggerRuntimeConfig.getProperty("user.account.activation.mail.from");

            String cc[] = new String[0];
            String bcc[] = new String[0];
            String to[] = new String[] { user.getEmailAddress() };
            String subject = resources.getString("user.account.activation.mail.subject");
            String content;

            String rootURL = WebloggerRuntimeConfig.getAbsoluteContextURL();

            StringBuffer sb = new StringBuffer();

            // activationURL=
            String activationURL = rootURL + "/roller-ui/register!activate.rol?activationCode="
                    + user.getActivationCode();
            sb.append(MessageFormat.format(resources.getString("user.account.activation.mail.content"),
                    new Object[] { user.getFullName(), user.getUserName(), activationURL }));
            content = sb.toString();

            sendHTMLMessage(from, to, cc, bcc, subject, content);
        } catch (MessagingException e) {
            throw new WebloggerException("ERROR: Problem sending activation email.", e);
        }
    }

    /**
     * Send email notification of new or newly approved comment.
     * TODO: Make the addressing options configurable on a per-website basis.
     * 
     * @param commentObject      The new comment
     * @param messages           Messages to be included in e-mail (or null). 
     *                           Errors will be assumed to be "validation errors" 
     *                           and messages will be assumed to be "from the system"
     */
    public static void sendEmailNotification(WeblogEntryComment commentObject, RollerMessages messages,
            I18nMessages resources, boolean notifySubscribers) throws MailingException {

        WeblogEntry entry = commentObject.getWeblogEntry();
        Weblog weblog = entry.getWebsite();
        User user = entry.getCreator();

        // Only send email if email notificaiton is enabled
        boolean notify = WebloggerRuntimeConfig.getBooleanProperty("users.comments.emailnotify");
        if (!notify || !weblog.getEmailComments().booleanValue()) {
            // notifications disabled, just bail
            return;
        }

        log.debug("Comment notification enabled ... preparing email");

        // Determine message and addressing options from init parameters
        boolean hideCommenterAddrs = WebloggerConfig
                .getBooleanProperty("comment.notification.hideCommenterAddresses");

        // use either the weblog configured from address or the site configured from address
        String from = weblog.getEmailFromAddress();
        if (StringUtils.isEmpty(from)) {
            // TODO: this should not be the users email address
            from = user.getEmailAddress();
        }

        // build list of email addresses to send notification to
        Set subscribers = new TreeSet();

        // If we are to notify subscribers, then...
        if (notifySubscribers) {
            log.debug("Sending notification email to all subscribers");

            // Get all the subscribers to this comment thread
            List comments = entry.getComments(true, true);
            for (Iterator it = comments.iterator(); it.hasNext();) {
                WeblogEntryComment comment = (WeblogEntryComment) it.next();
                if (!StringUtils.isEmpty(comment.getEmail())) {
                    // If user has commented twice,
                    // count the most recent notify setting
                    if (comment.getNotify().booleanValue()) {
                        // only add those with valid email
                        if (comment.getEmail().matches(EMAIL_ADDR_REGEXP)) {
                            subscribers.add(comment.getEmail());
                        }
                    } else {
                        // remove user who doesn't want to be notified
                        subscribers.remove(comment.getEmail());
                    }
                }
            }
        } else {
            log.debug("Sending notification email only to weblog owner");
        }

        // Form array of commenter addrs
        String[] commenterAddrs = (String[]) subscribers.toArray(new String[0]);

        //------------------------------------------
        // --- Form the messages to be sent -
        // Build separate owner and commenter (aka subscriber) messages

        // Determine with mime type to use for e-mail
        StringBuffer msg = new StringBuffer();
        StringBuffer ownermsg = new StringBuffer();
        boolean escapeHtml = !WebloggerRuntimeConfig.getBooleanProperty("users.comments.htmlenabled");

        // first the commenter message

        if (!escapeHtml) {
            msg.append("<html><body style=\"background: white; ");
            msg.append(" color: black; font-size: 12px\">");
        }

        if (!StringUtils.isEmpty(commentObject.getName())) {
            msg.append(commentObject.getName() + " " + resources.getString("email.comment.wrote") + ": ");
        } else {
            msg.append(resources.getString("email.comment.anonymous") + ": ");
        }

        msg.append((escapeHtml) ? "\n\n" : "<br /><br />");

        msg.append((escapeHtml) ? Utilities.escapeHTML(commentObject.getContent())
                : Utilities.transformToHTMLSubset(Utilities.escapeHTML(commentObject.getContent())));

        msg.append((escapeHtml) ? "\n\n----\n" : "<br /><br /><hr /><span style=\"font-size: 11px\">");
        msg.append(resources.getString("email.comment.respond") + ": ");
        msg.append((escapeHtml) ? "\n" : "<br />");

        // Build link back to comment
        String commentURL = WebloggerFactory.getWeblogger().getUrlStrategy().getWeblogCommentsURL(weblog, null,
                entry.getAnchor(), true);

        if (escapeHtml) {
            msg.append(commentURL);
        } else {
            msg.append("<a href=\"" + commentURL + "\">" + commentURL + "</a></span>");
        }

        // next the owner message

        // First, list any messages from the system that were passed in:
        if (messages.getMessageCount() > 0) {
            ownermsg.append((escapeHtml) ? "" : "<p>");
            ownermsg.append(resources.getString("commentServlet.email.thereAreSystemMessages"));
            ownermsg.append((escapeHtml) ? "\n\n" : "</p>");
            ownermsg.append((escapeHtml) ? "" : "<ul>");
        }
        for (Iterator it = messages.getMessages(); it.hasNext();) {
            RollerMessage rollerMessage = (RollerMessage) it.next();
            ownermsg.append((escapeHtml) ? "" : "<li>");
            ownermsg.append(MessageFormat.format(resources.getString(rollerMessage.getKey()),
                    (Object[]) rollerMessage.getArgs()));
            ownermsg.append((escapeHtml) ? "\n\n" : "</li>");
        }
        if (messages.getMessageCount() > 0) {
            ownermsg.append((escapeHtml) ? "\n\n" : "</ul>");
        }

        // Next, list any validation error messages that were passed in:
        if (messages.getErrorCount() > 0) {
            ownermsg.append((escapeHtml) ? "" : "<p>");
            ownermsg.append(resources.getString("commentServlet.email.thereAreErrorMessages"));
            ownermsg.append((escapeHtml) ? "\n\n" : "</p>");
            ownermsg.append((escapeHtml) ? "" : "<ul>");
        }
        for (Iterator it = messages.getErrors(); it.hasNext();) {
            RollerMessage rollerMessage = (RollerMessage) it.next();
            ownermsg.append((escapeHtml) ? "" : "<li>");
            ownermsg.append(MessageFormat.format(resources.getString(rollerMessage.getKey()),
                    (Object[]) rollerMessage.getArgs()));
            ownermsg.append((escapeHtml) ? "\n\n" : "</li>");
        }
        if (messages.getErrorCount() > 0) {
            ownermsg.append((escapeHtml) ? "\n\n" : "</ul>");
        }

        ownermsg.append(msg);

        // add link to weblog edit page so user can login to manage comments
        ownermsg.append((escapeHtml) ? "\n\n----\n" : "<br /><br /><hr /><span style=\"font-size: 11px\">");
        ownermsg.append("Link to comment management page:");
        ownermsg.append((escapeHtml) ? "\n" : "<br />");

        Map<String, String> parameters = new HashMap();
        parameters.put("bean.entryId", entry.getId());
        String deleteURL = WebloggerFactory.getWeblogger().getUrlStrategy().getActionURL("comments",
                "/roller-ui/authoring", weblog.getHandle(), parameters, true);

        if (escapeHtml) {
            ownermsg.append(deleteURL);
        } else {
            ownermsg.append("<a href=\"" + deleteURL + "\">" + deleteURL + "</a></span>");
            msg.append("</Body></html>");
            ownermsg.append("</Body></html>");
        }

        String subject = null;
        if ((subscribers.size() > 1) || (StringUtils.equals(commentObject.getEmail(), user.getEmailAddress()))) {
            subject = "RE: " + resources.getString("email.comment.title") + ": ";
        } else {
            subject = resources.getString("email.comment.title") + ": ";
        }
        subject += entry.getTitle();

        // send message to email recipients
        try {
            boolean isHtml = !escapeHtml;

            // Send separate messages to owner and commenters
            if (isHtml) {
                sendHTMLMessage(from, new String[] { user.getEmailAddress() }, null, null, subject,
                        ownermsg.toString());
            } else {
                sendTextMessage(from, new String[] { user.getEmailAddress() }, null, null, subject,
                        ownermsg.toString());
            }

            // now send to subscribers
            if (notifySubscribers && commenterAddrs.length > 0) {
                // If hiding commenter addrs, they go in Bcc: otherwise in the To: of the second message
                String[] to = hideCommenterAddrs ? null : commenterAddrs;
                String[] bcc = hideCommenterAddrs ? commenterAddrs : null;

                if (isHtml) {
                    sendHTMLMessage(from, to, null, bcc, subject, msg.toString());
                } else {
                    sendTextMessage(from, to, null, bcc, subject, msg.toString());
                }
            }
        } catch (Exception e) {
            log.warn("Exception sending comment notification mail", e);
            // This will log the stack trace if debug is enabled
            if (log.isDebugEnabled()) {
                log.debug(e);
            }
        }

        log.debug("Done sending email message");
    }

    public static void sendEmailApprovalNotifications(List<WeblogEntryComment> comments, I18nMessages resources)
            throws MailingException {

        RollerMessages messages = new RollerMessages();
        for (WeblogEntryComment comment : comments) {

            // Send email notifications because a new comment has been approved
            sendEmailNotification(comment, messages, resources, true);

            // Send approval notification to author of approved comment
            sendEmailApprovalNotification(comment, resources);
        }
    }

    /**
     * Send message to author of approved comment
     *
     * TODO: Make the addressing options configurable on a per-website basis.
     */
    public static void sendEmailApprovalNotification(WeblogEntryComment cd, I18nMessages resources)
            throws MailingException {

        WeblogEntry entry = cd.getWeblogEntry();
        Weblog weblog = entry.getWebsite();
        User user = entry.getCreator();

        // Only send email if email notificaiton is enabled
        boolean notify = WebloggerRuntimeConfig.getBooleanProperty("users.comments.emailnotify");
        if (!notify || !weblog.getEmailComments().booleanValue()) {
            // notifications disabled, just bail
            return;
        }

        log.debug("Comment notification enabled ... preparing email");

        // use either the weblog configured from address or the site configured from address
        String from = weblog.getEmailFromAddress();
        if (StringUtils.isEmpty(from)) {
            // TODO: this should not be the users email address
            from = user.getEmailAddress();
        }

        // form the message to be sent
        String subject = resources.getString("email.comment.commentApproved");

        StringBuffer msg = new StringBuffer();
        msg.append(resources.getString("email.comment.commentApproved"));
        msg.append("\n\n");
        msg.append(WebloggerFactory.getWeblogger().getUrlStrategy().getWeblogCommentsURL(weblog, null,
                entry.getAnchor(), true));

        // send message to author of approved comment
        try {
            sendTextMessage(from, // from
                    new String[] { cd.getEmail() }, // to
                    null, // cc
                    null, // bcc
                    subject, // subject
                    msg.toString()); // message
        } catch (Exception e) {
            log.warn("Exception sending comment mail: " + e.getMessage());
            // This will log the stack trace if debug is enabled
            if (log.isDebugEnabled()) {
                log.debug(e);
            }
        }

        log.debug("Done sending email message");
    }

    // agangolli: Incorporated suggested changes from Ken Blackler.

    /**
     * This method is used to send a Message with a pre-defined
     * mime-type.
     *
     * @param from e-mail address of sender
     * @param to e-mail address(es) of recipients
     * @param subject subject of e-mail
     * @param content the body of the e-mail
     * @param mimeType type of message, i.e. text/plain or text/html
     * @throws MessagingException the exception to indicate failure
     */
    public static void sendMessage(String from, String[] to, String[] cc, String[] bcc, String subject,
            String content, String mimeType) throws MessagingException {

        MailProvider mailProvider = WebloggerStartup.getMailProvider();
        if (mailProvider == null) {
            return;
        }

        Session session = mailProvider.getSession();
        Message message = new MimeMessage(session);

        // n.b. any default from address is expected to be determined by caller.
        if (!StringUtils.isEmpty(from)) {
            InternetAddress sentFrom = new InternetAddress(from);
            message.setFrom(sentFrom);
            if (log.isDebugEnabled())
                log.debug("e-mail from: " + sentFrom);
        }

        if (to != null) {
            InternetAddress[] sendTo = new InternetAddress[to.length];

            for (int i = 0; i < to.length; i++) {
                sendTo[i] = new InternetAddress(to[i]);
                if (log.isDebugEnabled())
                    log.debug("sending e-mail to: " + to[i]);
            }
            message.setRecipients(Message.RecipientType.TO, sendTo);
        }

        if (cc != null) {
            InternetAddress[] copyTo = new InternetAddress[cc.length];

            for (int i = 0; i < cc.length; i++) {
                copyTo[i] = new InternetAddress(cc[i]);
                if (log.isDebugEnabled())
                    log.debug("copying e-mail to: " + cc[i]);
            }
            message.setRecipients(Message.RecipientType.CC, copyTo);
        }

        if (bcc != null) {
            InternetAddress[] copyTo = new InternetAddress[bcc.length];

            for (int i = 0; i < bcc.length; i++) {
                copyTo[i] = new InternetAddress(bcc[i]);
                if (log.isDebugEnabled())
                    log.debug("blind copying e-mail to: " + bcc[i]);
            }
            message.setRecipients(Message.RecipientType.BCC, copyTo);
        }
        message.setSubject((subject == null) ? "(no subject)" : subject);
        message.setContent(content, mimeType);
        message.setSentDate(new java.util.Date());

        // First collect all the addresses together.
        Address[] remainingAddresses = message.getAllRecipients();
        int nAddresses = remainingAddresses.length;
        boolean bFailedToSome = false;

        SendFailedException sendex = new SendFailedException("Unable to send message to some recipients");

        Transport transport = mailProvider.getTransport();

        // Try to send while there remain some potentially good addresses
        try {
            do {
                // Avoid a loop if we are stuck
                nAddresses = remainingAddresses.length;

                try {
                    // Send to the list of remaining addresses, ignoring the addresses attached to the message
                    transport.sendMessage(message, remainingAddresses);
                } catch (SendFailedException ex) {
                    bFailedToSome = true;
                    sendex.setNextException(ex);

                    // Extract the remaining potentially good addresses
                    remainingAddresses = ex.getValidUnsentAddresses();
                }
            } while (remainingAddresses != null && remainingAddresses.length > 0
                    && remainingAddresses.length != nAddresses);

        } finally {
            transport.close();
        }

        if (bFailedToSome)
            throw sendex;
    }

    /**
     * This method is used to send a Text Message.
     *
     * @param from e-mail address of sender
     * @param to e-mail addresses of recipients
     * @param subject subject of e-mail
     * @param content the body of the e-mail
     * @throws MessagingException the exception to indicate failure
     */
    public static void sendTextMessage(String from, String[] to, String[] cc, String[] bcc, String subject,
            String content) throws MessagingException {
        sendMessage(from, to, cc, bcc, subject, content, "text/plain; charset=utf-8");
    }

    /**
     * This method overrides the sendTextMessage to specify
     * one receiver and mulitple cc recipients.
     *
     * @param from e-mail address of sender
     * @param to e-mail addresses of recipients
     * @param subject subject of e-mail
     * @param content the body of the e-mail
     * @throws MessagingException the exception to indicate failure
     */
    public static void sendTextMessage(String from, String to, String[] cc, String[] bcc, String subject,
            String content) throws MessagingException {
        String[] recipient = null;
        if (to != null)
            recipient = new String[] { to };

        sendMessage(from, recipient, cc, bcc, subject, content, "text/plain; charset=utf-8");
    }

    /**
     * This method overrides the sendTextMessage to specify
     * only one receiver and cc recipients, rather than
     * an array of recipients.
     *
     * @param from e-mail address of sender
     * @param to e-mail address of recipient
     * @param cc e-mail address of cc recipient
     * @param subject subject of e-mail
     * @param content the body of the e-mail
     * @throws MessagingException the exception to indicate failure
     */
    public static void sendTextMessage(String from, String to, String cc, String bcc, String subject,
            String content) throws MessagingException {
        String[] recipient = null;
        String[] copy = null;
        String[] bcopy = null;

        if (to != null)
            recipient = new String[] { to };
        if (cc != null)
            copy = new String[] { cc };
        if (bcc != null)
            bcopy = new String[] { bcc };

        sendMessage(from, recipient, copy, bcopy, subject, content, "text/plain; charset=utf-8");
    }

    /**
     * This method is used to send a HTML Message
     *
     * @param from e-mail address of sender
     * @param to e-mail address(es) of recipients
     * @param subject subject of e-mail
     * @param content the body of the e-mail
     * @throws MessagingException the exception to indicate failure
     */
    public static void sendHTMLMessage(String from, String[] to, String[] cc, String[] bcc, String subject,
            String content) throws MessagingException {
        sendMessage(from, to, cc, bcc, subject, content, "text/html; charset=utf-8");
    }

    /**
     * This method overrides the sendHTMLMessage to specify
     * only one sender, rather than an array of senders.
     *
     * @param from e-mail address of sender
     * @param to e-mail address of recipients
     * @param subject subject of e-mail
     * @param content the body of the e-mail
     * @throws MessagingException the exception to indicate failure
     */
    public static void sendHTMLMessage(String from, String to, String cc, String bcc, String subject,
            String content) throws MessagingException {
        String[] recipient = null;
        String[] copy = null;
        String[] bcopy = null;

        if (to != null)
            recipient = new String[] { to };
        if (cc != null)
            copy = new String[] { cc };
        if (bcc != null)
            bcopy = new String[] { bcc };

        sendMessage(from, recipient, copy, bcopy, subject, content, "text/html; charset=utf-8");
    }

    /**
     * This method overrides the sendHTMLMessage to specify
     * one receiver and mulitple cc recipients.
     *
     * @param from e-mail address of sender
     * @param to e-mail address of recipient
     * @param cc e-mail addresses of recipients
     * @param subject subject of e-mail
     * @param content the body of the e-mail
     * @throws MessagingException the exception to indicate failure
     */
    public static void sendHTMLMessage(String from, String to, String[] cc, String[] bcc, String subject,
            String content) throws MessagingException {
        String[] recipient = null;
        if (to != null)
            recipient = new String[] { to };

        sendMessage(from, recipient, cc, bcc, subject, content, "text/html; charset=utf-8");
    }

    /**
     * An exception thrown if there is a problem sending an email.
     */
    public class MailingException extends WebloggerException {
        public MailingException(Throwable t) {
            super(t);
        }
    }
}