/*
 * @(#) $Id: SimpleSender.java,v 1.3 2001/03/04 13:32:57 shin Exp $
 * $Revision: 1.3 $
 * Copyright (c) 2000 Shin Kinoshita All Rights Reserved.
 */
package com.sk_jp.mail;

import java.util.Properties;
import java.util.Date;

import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.Address;
import javax.mail.NoSuchProviderException;
import javax.mail.MessagingException;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
//
import javax.mail.internet.MimeUtility;

/**
 * メッセージ送信クラスです。
 * オブジェクトを生成してconnect/send/closeで送信することと、
 * いきなり送信を行うstaticなsendメソッドを用意しています。
 * @author Shin
 * @version $Revision: 1.3 $ $Date: 2001/03/04 13:32:57 $
 */
public class SimpleSender {
    private Session session;
    private Transport transport;

    /**
     * SMTP送信オブジェクトを生成します。
     * @exception NoSuchProviderException
     *            プロトコルに対応するProviderが見つからなかった
     */
    public SimpleSender() throws NoSuchProviderException {
        this("smtp");
    }

    /**
     * 指定プロトコルによる送信オブジェクトを生成します。
     * @param protocol 送信に用いるプロトコル名
     * @exception NoSuchProviderException
     *            プロトコルに対応するProviderが見つからなかった
     */
    public SimpleSender(String protocol) throws NoSuchProviderException {
        session = Session.getInstance(new Properties(), null);
        // "mail.debug"のみシステムプロパティの情報を利用する事にします。
        session.setDebug(Boolean.getBoolean("mail.debug"));
        transport = session.getTransport(protocol);
    }

    /**
     * サーバに接続します。
     * @param host 接続ホスト名
     * @exception MessagingException 接続に失敗
     */
    public void connect(String host) throws MessagingException {
        connect(host, -1, null, null);
    }

    /**
     * サーバに接続します。
     * @param host 接続ホスト名
     * @param port 接続ポート
     * @exception MessagingException 接続に失敗
     */
    public void connect(String host, int port) throws MessagingException {
        connect(host, port, null, null);
    }

    /**
     * サーバに接続します。
     * <P>SMTP AUTHを用いる場合に使用します。</P>
     * @param host 接続ホスト名
     * @param port ポート番号
     * @param user ユーザ名
     * @param pass パスワード
     * @exception MessagingException 接続に失敗
     */
    public synchronized void connect(String host,
                                     int port,
                                     String user,
                                     String pass) throws MessagingException {
        transport.connect(host, port, user, pass);
    }

    /**
     * サーバから切断します。
     */
    public synchronized void disconnect() {
        try {
            transport.close();
        } catch (MessagingException e) {}
    }

    /**
     * SMTP Authenticationの使用の有無を設定します。
     * SMTPProviderを使用する場合のみ有効です。
     */
    public void useSMTPAuth(boolean auth) {
        session.getProperties().put("mail.smtp.auth", String.valueOf(auth));
    }

    /**
     * 空のメッセージオブジェクトを生成します。
     * @return メッセージオブジェクト
     */
    public MimeMessage createMessage() {
        return new MimeMessage(session);
    }

    /**
     * メッセージにTo:From:X-Mailer:を付加します。
     * @param msg ヘッダを付加するメッセージ
     * @param to To:の内容
     * @param from From:の内容
     * @exception MessagingException ヘッダの設定に失敗
     * @exception AddressException to/fromが正しいメイルアドレスではない
     */
    public static void setHeaders(MimeMessage msg, String to, String from)
                throws MessagingException, AddressException {
        msg.setFrom(null);
        msg.addFrom(InternetAddress.parse(from, true));
        msg.setRecipients(MimeMessage.RecipientType.TO,
                          InternetAddress.parse(to, true));
        msg.setHeader("X-Mailer", "JavaMail Sender");
    }

    /**
     * メッセージを送信します。
     * MimeMessageに設定されたTo:に対して、
     * From:をenvelope-fromとして送信します。
     * @param msg 送信するメッセージ
     * @exception MessagingException 送信またはDateヘッダの設定に失敗
     */
    public void send(MimeMessage msg)
                throws MessagingException {
        send(msg, msg.getAllRecipients());
    }

    /**
     * メッセージを送信します。
     * 第二パラメタに指定されたenvelopeToに対して、
     * From:の内容をenvelope-fromとして送信します。
     * @param msg 送信するメッセージ
     * @param envelopeTo envelope-to(msgに設定されたRecipientsとは無関係です)
     * @exception MessagingException 送信またはDateヘッダの設定に失敗
     */
    public synchronized void send(MimeMessage msg, Address[] envelopeTo)
                throws MessagingException {
        msg.setSentDate(new Date());
        // Message-ID:にFromアドレスを使用します。
        session.getProperties().put("mail.from",
                ((InternetAddress)msg.getFrom()[0]).getAddress());
        msg.saveChanges();
        transport.sendMessage(msg, envelopeTo);
    }

    /**
     * envelope-from/envelope-toを指定してメッセージを送信します。
     * MimeMessageのTo:やFrom:は無視されます。
     * @param msg 送信するメッセージ
     * @param envelopeTo envelope-to(msgに設定されたRecipientsとは無関係です)
     * @param envelopeFrom envelope-from(msgに設定されたFromとは無関係です)
     * @exception MessagingException 送信またはDateヘッダの設定に失敗
     * @exception AddressException envelopeTo/envelopeFromが
     *                             正しいメイルアドレスではない
     */
    public synchronized void send(MimeMessage msg,
                                  String envelopeTo,
                                  String envelopeFrom)
                throws MessagingException, AddressException {

        session.getProperties().put("mail.smtp.from", envelopeFrom);
        send(msg, InternetAddress.parse(envelopeTo, true));
        session.getProperties().remove("mail.smtp.from");
    }

    /**
     * 日本語メッセージを送信します。
     * <p>
     * 単純なテキストメッセージ送信手段です。<br>
     * 指定したtoに指定subject/指定本文のメイルを送信します。
     * </p>
     * @param to To:の内容
     * @param from From:の内容
     * @param subject Subject:の内容
     * @param body 本文
     * @exception MessagingException 送信またはメッセージの構築に失敗
     * @exception AddressException envelopeTo/envelopeFromが
     *                             正しいメイルアドレスではない
     */
    public void send(String to, String from,
                     String subject, String body)
                throws MessagingException, AddressException {
        MimeMessage msg = createMessage();

        setHeaders(msg, to, from);

        try {
            msg.setSubject(
                    MimeUtility.encodeText(subject, "ISO-2022-JP", "B"));
        } catch (java.io.UnsupportedEncodingException e) {}
        msg.setText(body, "ISO-2022-JP");

        send(msg);
    }

    protected void finalize() throws Throwable {
        disconnect();
    }

    /**
     * 一通の日本語メッセージを送信するstaticメソッドです。
     * @param host SMTPサーバ
     * @param to To:の内容
     * @param from From:の内容
     * @param subject Subject:の内容
     * @param body 本文
     * @exception MessagingException 送信またはメッセージの構築に失敗
     * @exception AddressException メイルアドレスが不正
     */
    public static void send(String host,
                            String to,
                            String from,
                            String subject,
                            String body)
                throws MessagingException, AddressException {
        SimpleSender s = new SimpleSender();
        MimeMessage msg = s.createMessage();
        s.setHeaders(msg, to, from);
        try {
            msg.setSubject(
                    MimeUtility.encodeText(subject, "ISO-2022-JP", "B"));
        } catch (java.io.UnsupportedEncodingException e) {}
        msg.setText(body, "ISO-2022-JP");

        s.connect(host);
        s.send(msg);
        s.disconnect();
    }

    public static void main(String[] args) throws Exception {
        SimpleSender.send(
                "localhost",
                "postmaster@localhost",
                "shin@localhost",
                "てすと",
                "日本語メッセージのてすとです。");
    }
}

